From b4870a181489089185d4999cabf421041ec74a3f Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Fri, 13 Jun 2025 15:22:02 +0100 Subject: [PATCH] migration net9.0 --- .../{dotnet.yml => buildAndTest.yml} | 2 +- .github/workflows/main.yml | 7 - .gitignore | 1 + .vscode/launch.json | 2 +- README.md | 15 +- contrib/yavsc.service | 27 + src/Api/Api.csproj | 4 +- .../Google/Messaging/MessageWithPayLoad.cs | 1 + .../Interfaces/IBaseTrackedEntity.cs | 4 +- src/Yavsc.Abstract/Messaging/Notification.cs | 12 +- src/Yavsc.Abstract/Yavsc.Abstract.csproj | 2 +- ...50613122253_notificationTarget.Designer.cs | 3509 +++ .../20250613122253_notificationTarget.cs | 51 + ...250613123306_notificationNulls.Designer.cs | 3505 +++ .../20250613123306_notificationNulls.cs | 109 + .../20250613131533_trackedNulls.Designer.cs | 3505 +++ .../Migrations/20250613131533_trackedNulls.cs | 22 + .../20250613131836_blogNulls.Designer.cs | 3503 +++ .../Migrations/20250613131836_blogNulls.cs | 54 + ...39_BlogPostInputViewModelNulls.Designer.cs | 3502 +++ ...50613132139_BlogPostInputViewModelNulls.cs | 40 + .../20250613181510_ActivityNulls.Designer.cs | 3497 +++ .../20250613181510_ActivityNulls.cs | 108 + .../ApplicationDbContextModelSnapshot.cs | 120 +- .../Models/ApplicationDbContext.cs | 1 + src/Yavsc.Server/Models/Blog/BlogPost.cs | 4 +- .../Models/Messaging/DimissClicked.cs | 1 + src/Yavsc.Server/Models/Workflow/Activity.cs | 12 +- .../BlogSpot/BlogPostInputViewModel.cs | 3 +- src/Yavsc.Server/Yavsc.Server.csproj | 20 +- "src/Yavsc/\"BlogSpot\"" | 169 + .../Communicating/NotificationsController.cs | 1 + .../Haircut/HairCutCommandController.cs | 1 + src/Yavsc/Controllers/HomeController.cs | 3 - src/Yavsc/Extensions/HostingExtensions.cs | 4 +- src/Yavsc/Helpers/AsciiDocHelpers.cs | 97 +- src/Yavsc/Helpers/ControllerHelpers.cs | 2 +- src/Yavsc/Makefile | 27 +- src/Yavsc/Views/Home/Index.cshtml | 5 - src/Yavsc/Views/Notifications/Create.cshtml | 2 +- src/Yavsc/Views/Notifications/Delete.cshtml | 2 +- src/Yavsc/Views/Notifications/Details.cshtml | 2 +- src/Yavsc/Views/Notifications/Edit.cshtml | 2 +- src/Yavsc/Views/Notifications/Index.cshtml | 2 +- src/Yavsc/Views/Shared/_LoginPartial.cshtml | 1 - src/Yavsc/Views/_ViewImports.cshtml | 2 +- src/Yavsc/Yavsc.csproj | 33 +- ...y-afbdf233-abc3-4762-865b-884187518d95.xml | 16 + .../sampleWebAsWebApiClient.csproj | 14 +- .../wwwroot/lib/bootstrap/.babelrc.js | 12 + .../wwwroot/lib/bootstrap/.bower.json | 45 +- .../wwwroot/lib/bootstrap/.browserslistrc | 12 + .../lib/bootstrap/.bundlewatch.config.json | 66 + .../wwwroot/lib/bootstrap/.cspell.json | 131 + .../wwwroot/lib/bootstrap/.editorconfig | 11 + .../wwwroot/lib/bootstrap/.eslintignore | 9 + .../wwwroot/lib/bootstrap/.eslintrc.json | 240 + .../wwwroot/lib/bootstrap/.gitattributes | 8 + .../wwwroot/lib/bootstrap/.github/CODEOWNERS | 3 + .../lib/bootstrap/.github/CONTRIBUTING.md | 258 + .../.github/ISSUE_TEMPLATE/bug_report.yml | 62 + .../.github/ISSUE_TEMPLATE/config.yml | 4 + .../ISSUE_TEMPLATE/feature_request.yml | 29 + .../.github/PULL_REQUEST_TEMPLATE.md | 38 + .../wwwroot/lib/bootstrap/.github/SUPPORT.md | 11 + .../.github/codeql/codeql-config.yml | 3 + .../lib/bootstrap/.github/dependabot.yml | 26 + .../lib/bootstrap/.github/release-drafter.yml | 60 + .../.github/workflows/browserstack.yml | 46 + .../.github/workflows/bundlewatch.yml | 43 + .../workflows/calibreapp-image-actions.yml | 32 + .../bootstrap/.github/workflows/codeql.yml | 44 + .../bootstrap/.github/workflows/cspell.yml | 36 + .../lib/bootstrap/.github/workflows/css.yml | 40 + .../lib/bootstrap/.github/workflows/docs.yml | 50 + .../.github/workflows/issue-close-require.yml | 26 + .../.github/workflows/issue-labeled.yml | 26 + .../lib/bootstrap/.github/workflows/js.yml | 52 + .../lib/bootstrap/.github/workflows/lint.yml | 37 + .../bootstrap/.github/workflows/node-sass.yml | 49 + .../.github/workflows/release-notes.yml | 23 + .../wwwroot/lib/bootstrap/.prettierignore | 12 + .../wwwroot/lib/bootstrap/.stylelintignore | 6 + .../wwwroot/lib/bootstrap/.stylelintrc.json | 60 + .../wwwroot/lib/bootstrap/CODE_OF_CONDUCT.md | 132 + .../wwwroot/lib/bootstrap/Gruntfile.js | 531 - .../wwwroot/lib/bootstrap/LICENSE | 2 +- .../wwwroot/lib/bootstrap/README.md | 236 +- .../wwwroot/lib/bootstrap/SECURITY.md | 7 + .../wwwroot/lib/bootstrap/bower.json | 34 - .../wwwroot/lib/bootstrap/build/banner.mjs | 20 + .../lib/bootstrap/build/build-plugins.mjs | 108 + .../lib/bootstrap/build/change-version.mjs | 113 + .../wwwroot/lib/bootstrap/build/docs-prep.sh | 169 + .../lib/bootstrap/build/generate-sri.mjs | 64 + .../lib/bootstrap/build/postcss.config.mjs | 17 + .../lib/bootstrap/build/rollup.config.mjs | 59 + .../wwwroot/lib/bootstrap/build/vnu-jar.mjs | 66 + .../lib/bootstrap/build/zip-examples.mjs | 101 + .../wwwroot/lib/bootstrap/composer.json | 32 + .../wwwroot/lib/bootstrap/config.yml | 56 + .../lib/bootstrap/dist/css/bootstrap-grid.css | 4085 ++++ .../bootstrap/dist/css/bootstrap-grid.css.map | 1 + .../bootstrap/dist/css/bootstrap-grid.min.css | 6 + .../dist/css/bootstrap-grid.min.css.map | 1 + .../bootstrap/dist/css/bootstrap-grid.rtl.css | 4084 ++++ .../dist/css/bootstrap-grid.rtl.css.map | 1 + .../dist/css/bootstrap-grid.rtl.min.css | 6 + .../dist/css/bootstrap-grid.rtl.min.css.map | 1 + .../bootstrap/dist/css/bootstrap-reboot.css | 597 + .../dist/css/bootstrap-reboot.css.map | 1 + .../dist/css/bootstrap-reboot.min.css | 6 + .../dist/css/bootstrap-reboot.min.css.map | 1 + .../dist/css/bootstrap-reboot.rtl.css | 594 + .../dist/css/bootstrap-reboot.rtl.css.map | 1 + .../dist/css/bootstrap-reboot.rtl.min.css | 6 + .../dist/css/bootstrap-reboot.rtl.min.css.map | 1 + .../bootstrap/dist/css/bootstrap-theme.css | 587 - .../dist/css/bootstrap-theme.css.map | 1 - .../dist/css/bootstrap-theme.min.css | 5 - .../dist/css/bootstrap-utilities.css | 5406 +++++ .../dist/css/bootstrap-utilities.css.map | 1 + .../dist/css/bootstrap-utilities.min.css | 6 + .../dist/css/bootstrap-utilities.min.css.map | 1 + .../dist/css/bootstrap-utilities.rtl.css | 5397 +++++ .../dist/css/bootstrap-utilities.rtl.css.map | 1 + .../dist/css/bootstrap-utilities.rtl.min.css | 6 + .../css/bootstrap-utilities.rtl.min.css.map | 1 + .../lib/bootstrap/dist/css/bootstrap.css | 17695 +++++++++----- .../lib/bootstrap/dist/css/bootstrap.css.map | 2 +- .../lib/bootstrap/dist/css/bootstrap.min.css | 11 +- .../bootstrap/dist/css/bootstrap.min.css.map | 1 + .../lib/bootstrap/dist/css/bootstrap.rtl.css | 12016 ++++++++++ .../bootstrap/dist/css/bootstrap.rtl.css.map | 1 + .../bootstrap/dist/css/bootstrap.rtl.min.css | 6 + .../dist/css/bootstrap.rtl.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 288 - .../fonts/glyphicons-halflings-regular.ttf | Bin 45404 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes .../lib/bootstrap/dist/js/bootstrap.bundle.js | 6315 +++++ .../bootstrap/dist/js/bootstrap.bundle.js.map | 1 + .../bootstrap/dist/js/bootstrap.bundle.min.js | 7 + .../dist/js/bootstrap.bundle.min.js.map | 1 + .../lib/bootstrap/dist/js/bootstrap.esm.js | 4450 ++++ .../bootstrap/dist/js/bootstrap.esm.js.map | 1 + .../bootstrap/dist/js/bootstrap.esm.min.js | 7 + .../dist/js/bootstrap.esm.min.js.map | 1 + .../lib/bootstrap/dist/js/bootstrap.js | 6474 +++-- .../lib/bootstrap/dist/js/bootstrap.js.map | 1 + .../lib/bootstrap/dist/js/bootstrap.min.js | 12 +- .../bootstrap/dist/js/bootstrap.min.js.map | 1 + .../wwwroot/lib/bootstrap/dist/js/npm.js | 13 - .../fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 288 - .../fonts/glyphicons-halflings-regular.ttf | Bin 45404 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes .../wwwroot/lib/bootstrap/grunt/.jshintrc | 7 - .../bootstrap/grunt/bs-commonjs-generator.js | 30 - .../grunt/bs-glyphicons-data-generator.js | 42 - .../lib/bootstrap/grunt/bs-lessdoc-parser.js | 237 - .../bootstrap/grunt/bs-raw-files-generator.js | 44 - .../lib/bootstrap/grunt/configBridge.json | 46 - .../lib/bootstrap/grunt/sauce_browsers.yml | 82 - .../wwwroot/lib/bootstrap/js/.jscsrc | 42 - .../wwwroot/lib/bootstrap/js/.jshintrc | 15 - .../wwwroot/lib/bootstrap/js/affix.js | 162 - .../wwwroot/lib/bootstrap/js/alert.js | 94 - .../wwwroot/lib/bootstrap/js/button.js | 120 - .../wwwroot/lib/bootstrap/js/carousel.js | 237 - .../wwwroot/lib/bootstrap/js/collapse.js | 211 - .../wwwroot/lib/bootstrap/js/dist/alert.js | 90 + .../lib/bootstrap/js/dist/alert.js.map | 1 + .../lib/bootstrap/js/dist/base-component.js | 86 + .../bootstrap/js/dist/base-component.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/button.js | 79 + .../lib/bootstrap/js/dist/button.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/carousel.js | 388 + .../lib/bootstrap/js/dist/carousel.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/collapse.js | 249 + .../lib/bootstrap/js/dist/collapse.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/dom/data.js | 63 + .../lib/bootstrap/js/dist/dom/data.js.map | 1 + .../bootstrap/js/dist/dom/event-handler.js | 237 + .../js/dist/dom/event-handler.js.map | 1 + .../lib/bootstrap/js/dist/dom/manipulator.js | 72 + .../bootstrap/js/dist/dom/manipulator.js.map | 1 + .../bootstrap/js/dist/dom/selector-engine.js | 104 + .../js/dist/dom/selector-engine.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/dropdown.js | 405 + .../lib/bootstrap/js/dist/dropdown.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/modal.js | 320 + .../lib/bootstrap/js/dist/modal.js.map | 1 + .../lib/bootstrap/js/dist/offcanvas.js | 246 + .../lib/bootstrap/js/dist/offcanvas.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/popover.js | 96 + .../lib/bootstrap/js/dist/popover.js.map | 1 + .../lib/bootstrap/js/dist/scrollspy.js | 275 + .../lib/bootstrap/js/dist/scrollspy.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/tab.js | 285 + .../wwwroot/lib/bootstrap/js/dist/tab.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/toast.js | 198 + .../lib/bootstrap/js/dist/toast.js.map | 1 + .../wwwroot/lib/bootstrap/js/dist/tooltip.js | 545 + .../lib/bootstrap/js/dist/tooltip.js.map | 1 + .../lib/bootstrap/js/dist/util/backdrop.js | 139 + .../bootstrap/js/dist/util/backdrop.js.map | 1 + .../js/dist/util/component-functions.js | 42 + .../js/dist/util/component-functions.js.map | 1 + .../lib/bootstrap/js/dist/util/config.js | 68 + .../lib/bootstrap/js/dist/util/config.js.map | 1 + .../lib/bootstrap/js/dist/util/focustrap.js | 113 + .../bootstrap/js/dist/util/focustrap.js.map | 1 + .../lib/bootstrap/js/dist/util/index.js | 281 + .../lib/bootstrap/js/dist/util/index.js.map | 1 + .../lib/bootstrap/js/dist/util/sanitizer.js | 114 + .../bootstrap/js/dist/util/sanitizer.js.map | 1 + .../lib/bootstrap/js/dist/util/scrollbar.js | 113 + .../bootstrap/js/dist/util/scrollbar.js.map | 1 + .../lib/bootstrap/js/dist/util/swipe.js | 135 + .../lib/bootstrap/js/dist/util/swipe.js.map | 1 + .../js/dist/util/template-factory.js | 151 + .../js/dist/util/template-factory.js.map | 1 + .../wwwroot/lib/bootstrap/js/dropdown.js | 165 - .../wwwroot/lib/bootstrap/js/index.esm.js | 19 + .../wwwroot/lib/bootstrap/js/index.umd.js | 34 + .../wwwroot/lib/bootstrap/js/modal.js | 337 - .../wwwroot/lib/bootstrap/js/popover.js | 108 - .../wwwroot/lib/bootstrap/js/scrollspy.js | 172 - .../wwwroot/lib/bootstrap/js/src/alert.js | 87 + .../lib/bootstrap/js/src/base-component.js | 86 + .../wwwroot/lib/bootstrap/js/src/button.js | 72 + .../wwwroot/lib/bootstrap/js/src/carousel.js | 474 + .../wwwroot/lib/bootstrap/js/src/collapse.js | 297 + .../wwwroot/lib/bootstrap/js/src/dom/data.js | 55 + .../lib/bootstrap/js/src/dom/event-handler.js | 317 + .../lib/bootstrap/js/src/dom/manipulator.js | 71 + .../bootstrap/js/src/dom/selector-engine.js | 126 + .../wwwroot/lib/bootstrap/js/src/dropdown.js | 458 + .../wwwroot/lib/bootstrap/js/src/modal.js | 378 + .../wwwroot/lib/bootstrap/js/src/offcanvas.js | 282 + .../wwwroot/lib/bootstrap/js/src/popover.js | 97 + .../wwwroot/lib/bootstrap/js/src/scrollspy.js | 296 + .../wwwroot/lib/bootstrap/js/src/tab.js | 315 + .../wwwroot/lib/bootstrap/js/src/toast.js | 224 + .../wwwroot/lib/bootstrap/js/src/tooltip.js | 632 + .../lib/bootstrap/js/src/util/backdrop.js | 151 + .../js/src/util/component-functions.js | 35 + .../lib/bootstrap/js/src/util/config.js | 65 + .../lib/bootstrap/js/src/util/focustrap.js | 115 + .../lib/bootstrap/js/src/util/index.js | 306 + .../lib/bootstrap/js/src/util/sanitizer.js | 117 + .../lib/bootstrap/js/src/util/scrollbar.js | 114 + .../lib/bootstrap/js/src/util/swipe.js | 146 + .../bootstrap/js/src/util/template-factory.js | 160 + .../wwwroot/lib/bootstrap/js/tab.js | 155 - .../wwwroot/lib/bootstrap/js/tests/README.md | 73 + .../lib/bootstrap/js/tests/browsers.js | 80 + .../lib/bootstrap/js/tests/helpers/fixture.js | 47 + .../js/tests/integration/bundle-modularity.js | 9 + .../bootstrap/js/tests/integration/bundle.js | 6 + .../bootstrap/js/tests/integration/index.html | 67 + .../integration/rollup.bundle-modularity.js | 17 + .../js/tests/integration/rollup.bundle.js | 24 + .../lib/bootstrap/js/tests/karma.conf.js | 169 + .../lib/bootstrap/js/tests/unit/alert.spec.js | 259 + .../js/tests/unit/base-component.spec.js | 168 + .../bootstrap/js/tests/unit/button.spec.js | 183 + .../bootstrap/js/tests/unit/carousel.spec.js | 1572 ++ .../bootstrap/js/tests/unit/collapse.spec.js | 1062 + .../bootstrap/js/tests/unit/dom/data.spec.js | 104 + .../js/tests/unit/dom/event-handler.spec.js | 480 + .../js/tests/unit/dom/manipulator.spec.js | 135 + .../js/tests/unit/dom/selector-engine.spec.js | 414 + .../bootstrap/js/tests/unit/dropdown.spec.js | 2436 ++ .../bootstrap/js/tests/unit/jquery.spec.js | 60 + .../lib/bootstrap/js/tests/unit/modal.spec.js | 1329 ++ .../bootstrap/js/tests/unit/offcanvas.spec.js | 914 + .../bootstrap/js/tests/unit/popover.spec.js | 487 + .../bootstrap/js/tests/unit/scrollspy.spec.js | 980 + .../lib/bootstrap/js/tests/unit/tab.spec.js | 1252 + .../lib/bootstrap/js/tests/unit/toast.spec.js | 672 + .../bootstrap/js/tests/unit/tooltip.spec.js | 1585 ++ .../js/tests/unit/util/backdrop.spec.js | 321 + .../unit/util/component-functions.spec.js | 106 + .../js/tests/unit/util/config.spec.js | 166 + .../js/tests/unit/util/focustrap.spec.js | 218 + .../js/tests/unit/util/index.spec.js | 720 + .../js/tests/unit/util/sanitizer.spec.js | 163 + .../js/tests/unit/util/scrollbar.spec.js | 363 + .../js/tests/unit/util/swipe.spec.js | 291 + .../tests/unit/util/template-factory.spec.js | 306 + .../lib/bootstrap/js/tests/visual/alert.html | 48 + .../lib/bootstrap/js/tests/visual/button.html | 49 + .../bootstrap/js/tests/visual/carousel.html | 65 + .../bootstrap/js/tests/visual/collapse.html | 76 + .../bootstrap/js/tests/visual/dropdown.html | 205 + .../js/tests/visual/floating-label.html | 393 + .../lib/bootstrap/js/tests/visual/input.html | 78 + .../lib/bootstrap/js/tests/visual/modal.html | 279 + .../bootstrap/js/tests/visual/popover.html | 41 + .../bootstrap/js/tests/visual/scrollspy.html | 100 + .../lib/bootstrap/js/tests/visual/tab.html | 223 + .../lib/bootstrap/js/tests/visual/toast.html | 70 + .../bootstrap/js/tests/visual/tooltip.html | 138 + .../wwwroot/lib/bootstrap/js/tooltip.js | 514 - .../wwwroot/lib/bootstrap/js/transition.js | 59 - .../wwwroot/lib/bootstrap/less/.csscomb.json | 304 - .../wwwroot/lib/bootstrap/less/.csslintrc | 19 - .../wwwroot/lib/bootstrap/less/alerts.less | 73 - .../wwwroot/lib/bootstrap/less/badges.less | 66 - .../wwwroot/lib/bootstrap/less/bootstrap.less | 56 - .../lib/bootstrap/less/breadcrumbs.less | 26 - .../lib/bootstrap/less/button-groups.less | 244 - .../wwwroot/lib/bootstrap/less/buttons.less | 166 - .../wwwroot/lib/bootstrap/less/carousel.less | 269 - .../wwwroot/lib/bootstrap/less/close.less | 34 - .../wwwroot/lib/bootstrap/less/code.less | 69 - .../bootstrap/less/component-animations.less | 33 - .../wwwroot/lib/bootstrap/less/dropdowns.less | 216 - .../wwwroot/lib/bootstrap/less/forms.less | 607 - .../lib/bootstrap/less/glyphicons.less | 305 - .../wwwroot/lib/bootstrap/less/grid.less | 84 - .../lib/bootstrap/less/input-groups.less | 167 - .../wwwroot/lib/bootstrap/less/jumbotron.less | 52 - .../wwwroot/lib/bootstrap/less/labels.less | 64 - .../lib/bootstrap/less/list-group.less | 130 - .../wwwroot/lib/bootstrap/less/media.less | 66 - .../wwwroot/lib/bootstrap/less/mixins.less | 40 - .../lib/bootstrap/less/mixins/alerts.less | 14 - .../less/mixins/background-variant.less | 9 - .../bootstrap/less/mixins/border-radius.less | 18 - .../lib/bootstrap/less/mixins/buttons.less | 68 - .../bootstrap/less/mixins/center-block.less | 7 - .../lib/bootstrap/less/mixins/clearfix.less | 22 - .../lib/bootstrap/less/mixins/forms.less | 85 - .../lib/bootstrap/less/mixins/gradients.less | 59 - .../bootstrap/less/mixins/grid-framework.less | 91 - .../lib/bootstrap/less/mixins/grid.less | 122 - .../lib/bootstrap/less/mixins/hide-text.less | 21 - .../lib/bootstrap/less/mixins/image.less | 33 - .../lib/bootstrap/less/mixins/labels.less | 12 - .../lib/bootstrap/less/mixins/list-group.less | 30 - .../bootstrap/less/mixins/nav-divider.less | 10 - .../less/mixins/nav-vertical-align.less | 9 - .../lib/bootstrap/less/mixins/opacity.less | 8 - .../lib/bootstrap/less/mixins/pagination.less | 24 - .../lib/bootstrap/less/mixins/panels.less | 24 - .../bootstrap/less/mixins/progress-bar.less | 10 - .../bootstrap/less/mixins/reset-filter.less | 8 - .../less/mixins/responsive-visibility.less | 15 - .../lib/bootstrap/less/mixins/size.less | 10 - .../lib/bootstrap/less/mixins/tab-focus.less | 9 - .../lib/bootstrap/less/mixins/table-row.less | 28 - .../bootstrap/less/mixins/text-emphasis.less | 9 - .../less/mixins/vendor-prefixes.less | 227 - .../wwwroot/lib/bootstrap/less/modals.less | 150 - .../wwwroot/lib/bootstrap/less/navbar.less | 660 - .../wwwroot/lib/bootstrap/less/navs.less | 242 - .../wwwroot/lib/bootstrap/less/normalize.less | 424 - .../wwwroot/lib/bootstrap/less/pager.less | 54 - .../lib/bootstrap/less/pagination.less | 89 - .../wwwroot/lib/bootstrap/less/panels.less | 271 - .../wwwroot/lib/bootstrap/less/popovers.less | 131 - .../wwwroot/lib/bootstrap/less/print.less | 101 - .../lib/bootstrap/less/progress-bars.less | 87 - .../lib/bootstrap/less/responsive-embed.less | 35 - .../bootstrap/less/responsive-utilities.less | 194 - .../lib/bootstrap/less/scaffolding.less | 161 - .../wwwroot/lib/bootstrap/less/tables.less | 234 - .../wwwroot/lib/bootstrap/less/theme.less | 291 - .../lib/bootstrap/less/thumbnails.less | 36 - .../wwwroot/lib/bootstrap/less/tooltip.less | 101 - .../wwwroot/lib/bootstrap/less/type.less | 302 - .../wwwroot/lib/bootstrap/less/utilities.less | 55 - .../wwwroot/lib/bootstrap/less/variables.less | 867 - .../wwwroot/lib/bootstrap/less/wells.less | 29 - .../wwwroot/lib/bootstrap/nuget/MyGet.ps1 | 17 + .../lib/bootstrap/nuget/bootstrap.nuspec | 36 + .../wwwroot/lib/bootstrap/nuget/bootstrap.png | Bin 0 -> 6411 bytes .../lib/bootstrap/nuget/bootstrap.sass.nuspec | 36 + .../wwwroot/lib/bootstrap/package-lock.json | 19680 ++++++++++++++++ .../wwwroot/lib/bootstrap/package.js | 23 +- .../wwwroot/lib/bootstrap/package.json | 240 +- .../lib/bootstrap/scss/_accordion.scss | 153 + .../wwwroot/lib/bootstrap/scss/_alert.scss | 68 + .../wwwroot/lib/bootstrap/scss/_badge.scss | 38 + .../lib/bootstrap/scss/_breadcrumb.scss | 40 + .../lib/bootstrap/scss/_button-group.scss | 147 + .../wwwroot/lib/bootstrap/scss/_buttons.scss | 216 + .../wwwroot/lib/bootstrap/scss/_card.scss | 238 + .../wwwroot/lib/bootstrap/scss/_carousel.scss | 226 + .../wwwroot/lib/bootstrap/scss/_close.scss | 66 + .../lib/bootstrap/scss/_containers.scss | 41 + .../wwwroot/lib/bootstrap/scss/_dropdown.scss | 250 + .../wwwroot/lib/bootstrap/scss/_forms.scss | 9 + .../lib/bootstrap/scss/_functions.scss | 302 + .../wwwroot/lib/bootstrap/scss/_grid.scss | 39 + .../wwwroot/lib/bootstrap/scss/_helpers.scss | 12 + .../wwwroot/lib/bootstrap/scss/_images.scss | 42 + .../lib/bootstrap/scss/_list-group.scss | 199 + .../wwwroot/lib/bootstrap/scss/_maps.scss | 174 + .../wwwroot/lib/bootstrap/scss/_mixins.scss | 42 + .../wwwroot/lib/bootstrap/scss/_modal.scss | 240 + .../wwwroot/lib/bootstrap/scss/_nav.scss | 197 + .../wwwroot/lib/bootstrap/scss/_navbar.scss | 289 + .../lib/bootstrap/scss/_offcanvas.scss | 147 + .../lib/bootstrap/scss/_pagination.scss | 109 + .../lib/bootstrap/scss/_placeholders.scss | 51 + .../wwwroot/lib/bootstrap/scss/_popover.scss | 196 + .../wwwroot/lib/bootstrap/scss/_progress.scss | 68 + .../wwwroot/lib/bootstrap/scss/_reboot.scss | 611 + .../wwwroot/lib/bootstrap/scss/_root.scss | 187 + .../wwwroot/lib/bootstrap/scss/_spinners.scss | 85 + .../wwwroot/lib/bootstrap/scss/_tables.scss | 171 + .../wwwroot/lib/bootstrap/scss/_toasts.scss | 73 + .../wwwroot/lib/bootstrap/scss/_tooltip.scss | 119 + .../lib/bootstrap/scss/_transitions.scss | 27 + .../wwwroot/lib/bootstrap/scss/_type.scss | 106 + .../lib/bootstrap/scss/_utilities.scss | 806 + .../lib/bootstrap/scss/_variables-dark.scss | 102 + .../lib/bootstrap/scss/_variables.scss | 1753 ++ .../lib/bootstrap/scss/bootstrap-grid.scss | 62 + .../lib/bootstrap/scss/bootstrap-reboot.scss | 10 + .../bootstrap/scss/bootstrap-utilities.scss | 19 + .../wwwroot/lib/bootstrap/scss/bootstrap.scss | 52 + .../scss/forms/_floating-labels.scss | 97 + .../lib/bootstrap/scss/forms/_form-check.scss | 189 + .../bootstrap/scss/forms/_form-control.scss | 214 + .../lib/bootstrap/scss/forms/_form-range.scss | 91 + .../bootstrap/scss/forms/_form-select.scss | 80 + .../lib/bootstrap/scss/forms/_form-text.scss | 11 + .../bootstrap/scss/forms/_input-group.scss | 132 + .../lib/bootstrap/scss/forms/_labels.scss | 36 + .../lib/bootstrap/scss/forms/_validation.scss | 12 + .../lib/bootstrap/scss/helpers/_clearfix.scss | 3 + .../lib/bootstrap/scss/helpers/_color-bg.scss | 7 + .../scss/helpers/_colored-links.scss | 30 + .../bootstrap/scss/helpers/_focus-ring.scss | 5 + .../bootstrap/scss/helpers/_icon-link.scss | 25 + .../lib/bootstrap/scss/helpers/_position.scss | 36 + .../lib/bootstrap/scss/helpers/_ratio.scss | 26 + .../lib/bootstrap/scss/helpers/_stacks.scss | 15 + .../scss/helpers/_stretched-link.scss | 15 + .../scss/helpers/_text-truncation.scss | 7 + .../scss/helpers/_visually-hidden.scss | 8 + .../lib/bootstrap/scss/helpers/_vr.scss | 8 + .../lib/bootstrap/scss/mixins/_alert.scss | 18 + .../lib/bootstrap/scss/mixins/_backdrop.scss | 14 + .../lib/bootstrap/scss/mixins/_banner.scss | 7 + .../bootstrap/scss/mixins/_border-radius.scss | 78 + .../bootstrap/scss/mixins/_box-shadow.scss | 18 + .../bootstrap/scss/mixins/_breakpoints.scss | 127 + .../lib/bootstrap/scss/mixins/_buttons.scss | 70 + .../lib/bootstrap/scss/mixins/_caret.scss | 69 + .../lib/bootstrap/scss/mixins/_clearfix.scss | 9 + .../bootstrap/scss/mixins/_color-mode.scss | 21 + .../bootstrap/scss/mixins/_color-scheme.scss | 7 + .../lib/bootstrap/scss/mixins/_container.scss | 11 + .../lib/bootstrap/scss/mixins/_deprecate.scss | 10 + .../lib/bootstrap/scss/mixins/_forms.scss | 163 + .../lib/bootstrap/scss/mixins/_gradients.scss | 47 + .../lib/bootstrap/scss/mixins/_grid.scss | 151 + .../lib/bootstrap/scss/mixins/_image.scss | 16 + .../bootstrap/scss/mixins/_list-group.scss | 26 + .../lib/bootstrap/scss/mixins/_lists.scss | 7 + .../bootstrap/scss/mixins/_pagination.scss | 10 + .../mixins/_reset-text.scss} | 17 +- .../resize.less => scss/mixins/_resize.scss} | 4 +- .../scss/mixins/_table-variants.scss | 24 + .../mixins/_text-truncate.scss} | 4 +- .../bootstrap/scss/mixins/_transition.scss | 26 + .../lib/bootstrap/scss/mixins/_utilities.scss | 97 + .../scss/mixins/_visually-hidden.scss | 38 + .../lib/bootstrap/scss/tests/jasmine.js | 16 + .../_auto-import-of-variables-dark.test.scss | 7 + .../scss/tests/mixins/_color-modes.test.scss | 69 + .../_media-query-color-mode-full.test.scss | 8 + .../scss/tests/mixins/_utilities.test.scss | 393 + .../scss/tests/sass-true/register.js | 14 + .../bootstrap/scss/tests/sass-true/runner.js | 17 + .../scss/tests/utilities/_api.test.scss | 75 + .../lib/bootstrap/scss/utilities/_api.scss | 47 + .../lib/bootstrap/scss/vendor/_rfs.scss | 348 + .../lib/bootstrap/site/.prettierrc.json | 8 + .../lib/bootstrap/site/astro.config.ts | 33 + .../lib/bootstrap/site/data/breakpoints.yml | 35 + .../lib/bootstrap/site/data/colors.yml | 26 + .../lib/bootstrap/site/data/core-team.yml | 35 + .../lib/bootstrap/site/data/docs-versions.yml | 56 + .../lib/bootstrap/site/data/examples.yml | 141 + .../wwwroot/lib/bootstrap/site/data/grays.yml | 18 + .../wwwroot/lib/bootstrap/site/data/icons.yml | 27 + .../lib/bootstrap/site/data/plugins.yml | 47 + .../lib/bootstrap/site/data/sidebar.yml | 159 + .../lib/bootstrap/site/data/theme-colors.yml | 20 + .../lib/bootstrap/site/data/translations.yml | 24 + .../lib/bootstrap/site/postcss.config.cjs | 3 + .../bootstrap/site/src/assets/application.js | 16 + .../src/assets/examples/album-rtl/index.astro | 211 + .../src/assets/examples/album/index.astro | 210 + .../src/assets/examples/badges/badges.css | 3 + .../src/assets/examples/badges/index.astro | 146 + .../src/assets/examples/blog-rtl/index.astro | 255 + .../site/src/assets/examples/blog/blog.css | 39 + .../src/assets/examples/blog/blog.rtl.css | 39 + .../site/src/assets/examples/blog/index.astro | 307 + .../examples/breadcrumbs/breadcrumbs.css | 50 + .../assets/examples/breadcrumbs/index.astro | 85 + .../src/assets/examples/buttons/index.astro | 86 + .../assets/examples/carousel-rtl/index.astro | 166 + .../src/assets/examples/carousel/carousel.css | 82 + .../assets/examples/carousel/carousel.rtl.css | 74 + .../src/assets/examples/carousel/index.astro | 165 + .../examples/cheatsheet-rtl/index.astro | 1599 ++ .../assets/examples/cheatsheet/cheatsheet.css | 163 + .../assets/examples/cheatsheet/cheatsheet.js | 73 + .../examples/cheatsheet/cheatsheet.rtl.css | 156 + .../assets/examples/cheatsheet/index.astro | 1563 ++ .../assets/examples/checkout-rtl/index.astro | 231 + .../src/assets/examples/checkout/checkout.css | 3 + .../src/assets/examples/checkout/checkout.js | 19 + .../src/assets/examples/checkout/index.astro | 231 + .../site/src/assets/examples/cover/cover.css | 50 + .../src/assets/examples/cover/index.astro | 31 + .../examples/dashboard-rtl/dashboard.js | 49 + .../assets/examples/dashboard-rtl/index.astro | 330 + .../assets/examples/dashboard/dashboard.css | 48 + .../assets/examples/dashboard/dashboard.js | 49 + .../examples/dashboard/dashboard.rtl.css | 48 + .../src/assets/examples/dashboard/index.astro | 329 + .../assets/examples/dropdowns/dropdowns.css | 71 + .../src/assets/examples/dropdowns/index.astro | 459 + .../src/assets/examples/features/features.css | 26 + .../src/assets/examples/features/index.astro | 337 + .../examples/features/unsplash-photo-1.jpg | Bin 0 -> 10433 bytes .../examples/features/unsplash-photo-2.jpg | Bin 0 -> 113000 bytes .../examples/features/unsplash-photo-3.jpg | Bin 0 -> 40589 bytes .../src/assets/examples/footers/index.astro | 179 + .../site/src/assets/examples/grid/grid.css | 13 + .../site/src/assets/examples/grid/index.astro | 185 + .../src/assets/examples/headers/headers.css | 15 + .../src/assets/examples/headers/index.astro | 294 + .../assets/examples/heroes/bootstrap-docs.png | Bin 0 -> 369528 bytes .../examples/heroes/bootstrap-themes.png | Bin 0 -> 278159 bytes .../src/assets/examples/heroes/heroes.css | 3 + .../src/assets/examples/heroes/index.astro | 124 + .../src/assets/examples/jumbotron/index.astro | 43 + .../assets/examples/jumbotrons/index.astro | 79 + .../assets/examples/jumbotrons/jumbotrons.css | 1 + .../assets/examples/list-groups/index.astro | 222 + .../examples/list-groups/list-groups.css | 63 + .../src/assets/examples/masonry/index.astro | 106 + .../src/assets/examples/modals/index.astro | 147 + .../src/assets/examples/modals/modals.css | 7 + .../assets/examples/navbar-bottom/index.astro | 42 + .../assets/examples/navbar-fixed/index.astro | 40 + .../examples/navbar-fixed/navbar-fixed.css | 5 + .../assets/examples/navbar-static/index.astro | 40 + .../examples/navbar-static/navbar-static.css | 4 + .../examples/navbars-offcanvas/index.astro | 147 + .../navbars-offcanvas/navbars-offcanvas.css | 7 + .../src/assets/examples/navbars/index.astro | 450 + .../src/assets/examples/navbars/navbars.css | 7 + .../examples/offcanvas-navbar/index.astro | 140 + .../offcanvas-navbar/offcanvas-navbar.css | 52 + .../offcanvas-navbar/offcanvas-navbar.js | 7 + .../src/assets/examples/pricing/index.astro | 186 + .../src/assets/examples/pricing/pricing.css | 11 + .../src/assets/examples/product/index.astro | 187 + .../src/assets/examples/product/product.css | 74 + .../src/assets/examples/sidebars/index.astro | 352 + .../src/assets/examples/sidebars/sidebars.css | 63 + .../src/assets/examples/sidebars/sidebars.js | 8 + .../src/assets/examples/sign-in/index.astro | 32 + .../src/assets/examples/sign-in/sign-in.css | 25 + .../examples/starter-template/index.astro | 108 + .../examples/sticky-footer-navbar/index.astro | 52 + .../sticky-footer-navbar.css | 7 + .../assets/examples/sticky-footer/index.astro | 23 + .../examples/sticky-footer/sticky-footer.css | 9 + .../site/src/assets/partials/sidebar.js | 30 + .../site/src/assets/partials/snippets.js | 168 + .../lib/bootstrap/site/src/assets/search.js | 59 + .../lib/bootstrap/site/src/assets/snippets.js | 15 + .../bootstrap/site/src/assets/stackblitz.js | 89 + .../bootstrap/site/src/components/Ads.astro | 9 + .../site/src/components/DocsSidebar.astro | 84 + .../site/src/components/Scripts.astro | 17 + .../site/src/components/TableOfContents.astro | 26 + .../site/src/components/footer/Footer.astro | 95 + .../site/src/components/head/Analytics.astro | 6 + .../site/src/components/head/Favicons.astro | 11 + .../site/src/components/head/Head.astro | 54 + .../site/src/components/head/Scss.astro | 7 + .../site/src/components/head/Social.astro | 31 + .../site/src/components/head/Stylesheet.astro | 13 + .../site/src/components/header/Header.astro | 20 + .../site/src/components/header/LinkItem.astro | 24 + .../src/components/header/Navigation.astro | 131 + .../site/src/components/header/Skippy.astro | 22 + .../site/src/components/header/Versions.astro | 96 + .../src/components/home/CSSVariables.astro | 71 + .../components/home/ComponentUtilities.astro | 158 + .../site/src/components/home/Customize.astro | 69 + .../site/src/components/home/GetStarted.astro | 115 + .../site/src/components/home/Icons.astro | 28 + .../site/src/components/home/MastHead.astro | 60 + .../site/src/components/home/Plugins.astro | 90 + .../site/src/components/home/Themes.astro | 35 + .../icons/BootstrapWhiteFillIcon.astro | 18 + .../components/icons/CircleSquareIcon.astro | 23 + .../components/icons/DropletFillIcon.astro | 24 + .../src/components/icons/GitHubIcon.astro | 24 + .../src/components/icons/HamburgerIcon.astro | 23 + .../components/icons/OpenCollectiveIcon.astro | 26 + .../site/src/components/icons/Symbols.astro | 148 + .../site/src/components/icons/XIcon.astro | 23 + .../src/components/shortcodes/AddedIn.astro | 16 + .../src/components/shortcodes/BsTable.astro | 16 + .../src/components/shortcodes/Callout.astro | 44 + .../CalloutDeprecatedDarkVariants.astro | 19 + .../site/src/components/shortcodes/Code.astro | 156 + .../components/shortcodes/DeprecatedIn.astro | 17 + .../src/components/shortcodes/Example.astro | 105 + .../src/components/shortcodes/GuideFooter.mdx | 3 + .../shortcodes/JsDataAttributes.mdx | 5 + .../src/components/shortcodes/JsDismiss.astro | 29 + .../src/components/shortcodes/JsDocs.astro | 69 + .../components/shortcodes/Placeholder.astro | 27 + .../src/components/shortcodes/ScssDocs.astro | 71 + .../src/components/shortcodes/Table.astro | 31 + .../src/components/shortcodes/TableContent.md | 28 + .../content/callouts/danger-async-methods.md | 1 + .../callouts/info-mediaqueries-breakpoints.md | 1 + .../src/content/callouts/info-npm-starter.md | 1 + .../callouts/info-prefersreducedmotion.md | 1 + .../src/content/callouts/info-sanitizer.md | 1 + .../warning-color-assistive-technologies.md | 1 + .../warning-data-bs-title-vs-title.md | 1 + .../content/callouts/warning-input-support.md | 1 + .../lib/bootstrap/site/src/content/config.ts | 45 + .../site/src/content/docs/about/brand.mdx | 41 + .../site/src/content/docs/about/license.mdx | 32 + .../site/src/content/docs/about/overview.mdx | 27 + .../site/src/content/docs/about/team.mdx | 23 + .../src/content/docs/about/translations.mdx | 20 + .../src/content/docs/components/accordion.mdx | 240 + .../src/content/docs/components/alerts.mdx | 218 + .../src/content/docs/components/badge.mdx | 83 + .../content/docs/components/breadcrumb.mdx | 98 + .../content/docs/components/button-group.mdx | 220 + .../src/content/docs/components/buttons.mdx | 227 + .../site/src/content/docs/components/card.mdx | 673 + .../src/content/docs/components/carousel.mdx | 420 + .../content/docs/components/close-button.mdx | 46 + .../src/content/docs/components/collapse.mdx | 184 + .../src/content/docs/components/dropdowns.mdx | 1065 + .../content/docs/components/list-group.mdx | 448 + .../src/content/docs/components/modal.mdx | 835 + .../src/content/docs/components/navbar.mdx | 761 + .../src/content/docs/components/navs-tabs.mdx | 662 + .../src/content/docs/components/offcanvas.mdx | 330 + .../content/docs/components/pagination.mdx | 171 + .../content/docs/components/placeholders.mdx | 133 + .../src/content/docs/components/popovers.mdx | 257 + .../src/content/docs/components/progress.mdx | 174 + .../src/content/docs/components/scrollspy.mdx | 421 + .../src/content/docs/components/spinners.mdx | 175 + .../src/content/docs/components/toasts.mdx | 363 + .../src/content/docs/components/tooltips.mdx | 270 + .../site/src/content/docs/content/figures.mdx | 27 + .../site/src/content/docs/content/images.mdx | 51 + .../site/src/content/docs/content/reboot.mdx | 443 + .../site/src/content/docs/content/tables.mdx | 820 + .../src/content/docs/content/typography.mdx | 260 + .../content/docs/customize/color-modes.mdx | 253 + .../site/src/content/docs/customize/color.mdx | 513 + .../src/content/docs/customize/components.mdx | 75 + .../content/docs/customize/css-variables.mdx | 70 + .../src/content/docs/customize/optimize.mdx | 88 + .../src/content/docs/customize/options.mdx | 31 + .../src/content/docs/customize/overview.mdx | 51 + .../site/src/content/docs/customize/sass.mdx | 363 + .../site/src/content/docs/docsref.mdx | 45 + .../site/src/content/docs/extend/approach.mdx | 84 + .../site/src/content/docs/extend/icons.mdx | 42 + .../src/content/docs/forms/checks-radios.mdx | 311 + .../content/docs/forms/floating-labels.mdx | 156 + .../src/content/docs/forms/form-control.mdx | 166 + .../src/content/docs/forms/input-group.mdx | 305 + .../site/src/content/docs/forms/layout.mdx | 307 + .../site/src/content/docs/forms/overview.mdx | 110 + .../site/src/content/docs/forms/range.mdx | 39 + .../site/src/content/docs/forms/select.mdx | 69 + .../src/content/docs/forms/validation.mdx | 380 + .../docs/getting-started/accessibility.mdx | 59 + .../docs/getting-started/best-practices.mdx | 18 + .../docs/getting-started/browsers-devices.mdx | 73 + .../content/docs/getting-started/contents.mdx | 111 + .../docs/getting-started/contribute.mdx | 65 + .../content/docs/getting-started/download.mdx | 152 + .../docs/getting-started/introduction.mdx | 154 + .../docs/getting-started/javascript.mdx | 304 + .../content/docs/getting-started/parcel.mdx | 165 + .../src/content/docs/getting-started/rfs.mdx | 84 + .../src/content/docs/getting-started/rtl.mdx | 186 + .../src/content/docs/getting-started/vite.mdx | 196 + .../content/docs/getting-started/webpack.mdx | 358 + .../src/content/docs/helpers/clearfix.mdx | 32 + .../content/docs/helpers/color-background.mdx | 43 + .../content/docs/helpers/colored-links.mdx | 33 + .../src/content/docs/helpers/focus-ring.mdx | 57 + .../src/content/docs/helpers/icon-link.mdx | 88 + .../src/content/docs/helpers/position.mdx | 61 + .../site/src/content/docs/helpers/ratio.mdx | 71 + .../site/src/content/docs/helpers/stacks.mdx | 72 + .../content/docs/helpers/stretched-link.mdx | 64 + .../content/docs/helpers/text-truncation.mdx | 19 + .../content/docs/helpers/vertical-rule.mdx | 46 + .../content/docs/helpers/visually-hidden.mdx | 25 + .../src/content/docs/layout/breakpoints.mdx | 170 + .../site/src/content/docs/layout/columns.mdx | 325 + .../src/content/docs/layout/containers.mdx | 93 + .../site/src/content/docs/layout/css-grid.mdx | 236 + .../site/src/content/docs/layout/grid.mdx | 480 + .../site/src/content/docs/layout/gutters.mdx | 151 + .../src/content/docs/layout/utilities.mdx | 23 + .../site/src/content/docs/layout/z-index.mdx | 14 + .../site/src/content/docs/migration.mdx | 744 + .../site/src/content/docs/utilities/api.mdx | 621 + .../src/content/docs/utilities/background.mdx | 137 + .../src/content/docs/utilities/borders.mdx | 172 + .../src/content/docs/utilities/colors.mdx | 131 + .../src/content/docs/utilities/display.mdx | 104 + .../site/src/content/docs/utilities/flex.mdx | 653 + .../site/src/content/docs/utilities/float.mdx | 49 + .../content/docs/utilities/interactions.mdx | 36 + .../site/src/content/docs/utilities/link.mdx | 84 + .../src/content/docs/utilities/object-fit.mdx | 59 + .../src/content/docs/utilities/opacity.mdx | 34 + .../src/content/docs/utilities/overflow.mdx | 97 + .../src/content/docs/utilities/position.mdx | 118 + .../src/content/docs/utilities/shadows.mdx | 26 + .../src/content/docs/utilities/sizing.mdx | 52 + .../src/content/docs/utilities/spacing.mdx | 144 + .../site/src/content/docs/utilities/text.mdx | 137 + .../content/docs/utilities/vertical-align.mdx | 42 + .../src/content/docs/utilities/visibility.mdx | 35 + .../src/content/docs/utilities/z-index.mdx | 47 + .../wwwroot/lib/bootstrap/site/src/env.d.ts | 10 + .../site/src/layouts/BaseLayout.astro | 86 + .../site/src/layouts/DocsLayout.astro | 136 + .../site/src/layouts/ExamplesLayout.astro | 151 + .../site/src/layouts/RedirectLayout.astro | 23 + .../site/src/layouts/SingleLayout.astro | 37 + .../site/src/layouts/partials/BsThemes.astro | 30 + .../src/layouts/partials/ExamplesMain.astro | 95 + .../site/src/layouts/partials/Icons.astro | 23 + .../layouts/partials/ResponsiveImage.astro | 36 + .../src/layouts/partials/ThemeToggler.astro | 60 + .../lib/bootstrap/site/src/libs/astro.ts | 195 + .../lib/bootstrap/site/src/libs/bootstrap.ts | 48 + .../lib/bootstrap/site/src/libs/config.ts | 89 + .../lib/bootstrap/site/src/libs/content.ts | 12 + .../lib/bootstrap/site/src/libs/data.ts | 146 + .../lib/bootstrap/site/src/libs/examples.ts | 74 + .../lib/bootstrap/site/src/libs/icon.ts | 5 + .../lib/bootstrap/site/src/libs/image.ts | 16 + .../lib/bootstrap/site/src/libs/layout.ts | 7 + .../lib/bootstrap/site/src/libs/path.ts | 71 + .../bootstrap/site/src/libs/placeholder.ts | 251 + .../lib/bootstrap/site/src/libs/prism.ts | 93 + .../lib/bootstrap/site/src/libs/rehype.ts | 34 + .../lib/bootstrap/site/src/libs/remark.ts | 161 + .../lib/bootstrap/site/src/libs/toc.ts | 42 + .../lib/bootstrap/site/src/libs/utils.ts | 44 + .../lib/bootstrap/site/src/libs/validation.ts | 26 + .../lib/bootstrap/site/src/pages/404.astro | 17 + .../bootstrap/site/src/pages/[...alias].astro | 56 + .../src/pages/docs/[version]/[...slug].astro | 25 + .../docs/[version]/examples/[...asset].ts | 32 + .../[version]/examples/[...example].astro | 40 + .../pages/docs/[version]/examples/index.astro | 33 + .../site/src/pages/docs/[version]/index.astro | 15 + .../bootstrap/site/src/pages/docs/index.astro | 6 + .../site/src/pages/docs/versions.astro | 53 + .../bootstrap/site/src/pages/examples.astro | 6 + .../lib/bootstrap/site/src/pages/index.astro | 24 + .../bootstrap/site/src/pages/robots.txt.ts | 20 + .../site/src/plugins/algolia-plugin.js | 22 + .../site/src/plugins/stackblitz-plugin.js | 22 + .../lib/bootstrap/site/src/scss/_ads.scss | 38 + .../lib/bootstrap/site/src/scss/_anchor.scss | 21 + .../lib/bootstrap/site/src/scss/_brand.scss | 60 + .../lib/bootstrap/site/src/scss/_buttons.scss | 52 + .../bootstrap/site/src/scss/_callouts.scss | 40 + .../site/src/scss/_clipboard-js.scss | 44 + .../lib/bootstrap/site/src/scss/_colors.scss | 172 + .../site/src/scss/_component-examples.scss | 404 + .../lib/bootstrap/site/src/scss/_content.scss | 167 + .../lib/bootstrap/site/src/scss/_footer.scss | 16 + .../lib/bootstrap/site/src/scss/_layout.scss | 57 + .../bootstrap/site/src/scss/_masthead.scss | 123 + .../lib/bootstrap/site/src/scss/_navbar.scss | 133 + .../site/src/scss/_placeholder-img.scss | 15 + .../bootstrap/site/src/scss/_scrolling.scss | 16 + .../lib/bootstrap/site/src/scss/_search.scss | 173 + .../lib/bootstrap/site/src/scss/_sidebar.scss | 64 + .../lib/bootstrap/site/src/scss/_skippy.scss | 7 + .../lib/bootstrap/site/src/scss/_syntax.scss | 158 + .../lib/bootstrap/site/src/scss/_toc.scss | 93 + .../bootstrap/site/src/scss/_variables.scss | 35 + .../lib/bootstrap/site/src/scss/docs.scss | 58 + .../bootstrap/site/src/scss/docs_search.scss | 14 + .../bootstrap/site/src/types/auto-import.d.ts | 21 + .../lib/bootstrap/site/src/types/window.d.ts | 25 + .../wwwroot/lib/bootstrap/site/static/CNAME | 1 + .../assets/brand/bootstrap-logo-black.svg | 1 + .../assets/brand/bootstrap-logo-shadow.png | Bin 0 -> 13093 bytes .../assets/brand/bootstrap-logo-shadow@2x.png | Bin 0 -> 42797 bytes .../assets/brand/bootstrap-logo-white.svg | 1 + .../[version]/assets/brand/bootstrap-logo.svg | 1 + .../assets/brand/bootstrap-social.png | Bin 0 -> 699429 bytes .../[version]/assets/img/bootstrap-icons.png | Bin 0 -> 40346 bytes .../assets/img/bootstrap-icons@2x.png | Bin 0 -> 120489 bytes .../assets/img/bootstrap-themes-collage.png | Bin 0 -> 73534 bytes .../img/bootstrap-themes-collage@2x.png | Bin 0 -> 237638 bytes .../[version]/assets/img/bootstrap-themes.png | Bin 0 -> 88695 bytes .../assets/img/bootstrap-themes@2x.png | Bin 0 -> 278159 bytes .../assets/img/examples/album-rtl.png | Bin 0 -> 6313 bytes .../assets/img/examples/album-rtl@2x.png | Bin 0 -> 15241 bytes .../[version]/assets/img/examples/album.png | Bin 0 -> 10667 bytes .../assets/img/examples/album@2x.png | Bin 0 -> 24904 bytes .../[version]/assets/img/examples/badges.png | Bin 0 -> 6180 bytes .../assets/img/examples/badges@2x.png | Bin 0 -> 14231 bytes .../assets/img/examples/blog-rtl.png | Bin 0 -> 12545 bytes .../assets/img/examples/blog-rtl@2x.png | Bin 0 -> 31035 bytes .../[version]/assets/img/examples/blog.png | Bin 0 -> 15245 bytes .../[version]/assets/img/examples/blog@2x.png | Bin 0 -> 36944 bytes .../assets/img/examples/breadcrumbs.png | Bin 0 -> 2359 bytes .../assets/img/examples/breadcrumbs@2x.png | Bin 0 -> 6024 bytes .../[version]/assets/img/examples/buttons.png | Bin 0 -> 4493 bytes .../assets/img/examples/buttons@2x.png | Bin 0 -> 9827 bytes .../assets/img/examples/carousel-rtl.png | Bin 0 -> 10242 bytes .../assets/img/examples/carousel-rtl@2x.png | Bin 0 -> 24414 bytes .../assets/img/examples/carousel.png | Bin 0 -> 13170 bytes .../assets/img/examples/carousel@2x.png | Bin 0 -> 31271 bytes .../assets/img/examples/cheatsheet-rtl.png | Bin 0 -> 6089 bytes .../assets/img/examples/cheatsheet-rtl@2x.png | Bin 0 -> 13863 bytes .../assets/img/examples/cheatsheet.png | Bin 0 -> 8132 bytes .../assets/img/examples/cheatsheet@2x.png | Bin 0 -> 19324 bytes .../assets/img/examples/checkout-rtl.png | Bin 0 -> 8847 bytes .../assets/img/examples/checkout-rtl@2x.png | Bin 0 -> 21952 bytes .../assets/img/examples/checkout.png | Bin 0 -> 7639 bytes .../assets/img/examples/checkout@2x.png | Bin 0 -> 19105 bytes .../[version]/assets/img/examples/cover.png | Bin 0 -> 7240 bytes .../assets/img/examples/cover@2x.png | Bin 0 -> 17927 bytes .../assets/img/examples/dashboard-rtl.png | Bin 0 -> 8261 bytes .../assets/img/examples/dashboard-rtl@2x.png | Bin 0 -> 19363 bytes .../assets/img/examples/dashboard.png | Bin 0 -> 11914 bytes .../assets/img/examples/dashboard@2x.png | Bin 0 -> 26556 bytes .../assets/img/examples/dropdowns.png | Bin 0 -> 6146 bytes .../assets/img/examples/dropdowns@2x.png | Bin 0 -> 14972 bytes .../assets/img/examples/features.png | Bin 0 -> 6067 bytes .../assets/img/examples/features@2x.png | Bin 0 -> 14971 bytes .../[version]/assets/img/examples/footers.png | Bin 0 -> 4295 bytes .../assets/img/examples/footers@2x.png | Bin 0 -> 10209 bytes .../[version]/assets/img/examples/grid.png | Bin 0 -> 9392 bytes .../[version]/assets/img/examples/grid@2x.png | Bin 0 -> 24996 bytes .../[version]/assets/img/examples/headers.png | Bin 0 -> 5180 bytes .../assets/img/examples/headers@2x.png | Bin 0 -> 12565 bytes .../[version]/assets/img/examples/heroes.png | Bin 0 -> 9017 bytes .../assets/img/examples/heroes@2x.png | Bin 0 -> 23433 bytes .../assets/img/examples/jumbotron.png | Bin 0 -> 9155 bytes .../assets/img/examples/jumbotron@2x.png | Bin 0 -> 23316 bytes .../assets/img/examples/jumbotrons.png | Bin 0 -> 6463 bytes .../assets/img/examples/jumbotrons@2x.png | Bin 0 -> 13933 bytes .../assets/img/examples/list-groups.png | Bin 0 -> 7098 bytes .../assets/img/examples/list-groups@2x.png | Bin 0 -> 17715 bytes .../[version]/assets/img/examples/masonry.png | Bin 0 -> 15234 bytes .../assets/img/examples/masonry@2x.png | Bin 0 -> 37338 bytes .../[version]/assets/img/examples/modals.png | Bin 0 -> 4814 bytes .../assets/img/examples/modals@2x.png | Bin 0 -> 11623 bytes .../assets/img/examples/navbar-bottom.png | Bin 0 -> 4747 bytes .../assets/img/examples/navbar-bottom@2x.png | Bin 0 -> 11588 bytes .../assets/img/examples/navbar-fixed.png | Bin 0 -> 5864 bytes .../assets/img/examples/navbar-fixed@2x.png | Bin 0 -> 13971 bytes .../assets/img/examples/navbar-static.png | Bin 0 -> 6538 bytes .../assets/img/examples/navbar-static@2x.png | Bin 0 -> 15127 bytes .../assets/img/examples/navbars-offcanvas.png | Bin 0 -> 6781 bytes .../img/examples/navbars-offcanvas@2x.png | Bin 0 -> 16913 bytes .../[version]/assets/img/examples/navbars.png | Bin 0 -> 12963 bytes .../assets/img/examples/navbars@2x.png | Bin 0 -> 31168 bytes .../assets/img/examples/offcanvas-navbar.png | Bin 0 -> 9673 bytes .../img/examples/offcanvas-navbar@2x.png | Bin 0 -> 23926 bytes .../[version]/assets/img/examples/pricing.png | Bin 0 -> 11621 bytes .../assets/img/examples/pricing@2x.png | Bin 0 -> 29073 bytes .../[version]/assets/img/examples/product.png | Bin 0 -> 12906 bytes .../assets/img/examples/product@2x.png | Bin 0 -> 27953 bytes .../assets/img/examples/sidebars.png | Bin 0 -> 12287 bytes .../assets/img/examples/sidebars@2x.png | Bin 0 -> 33499 bytes .../[version]/assets/img/examples/sign-in.png | Bin 0 -> 2199 bytes .../assets/img/examples/sign-in@2x.png | Bin 0 -> 4568 bytes .../assets/img/examples/starter-template.png | Bin 0 -> 7753 bytes .../img/examples/starter-template@2x.png | Bin 0 -> 20134 bytes .../img/examples/sticky-footer-navbar.png | Bin 0 -> 6874 bytes .../img/examples/sticky-footer-navbar@2x.png | Bin 0 -> 15720 bytes .../assets/img/examples/sticky-footer.png | Bin 0 -> 4278 bytes .../assets/img/examples/sticky-footer@2x.png | Bin 0 -> 9665 bytes .../img/favicons/android-chrome-192x192.png | Bin 0 -> 8166 bytes .../img/favicons/android-chrome-512x512.png | Bin 0 -> 23009 bytes .../assets/img/favicons/apple-touch-icon.png | Bin 0 -> 7307 bytes .../assets/img/favicons/favicon-16x16.png | Bin 0 -> 525 bytes .../assets/img/favicons/favicon-32x32.png | Bin 0 -> 1152 bytes .../[version]/assets/img/favicons/favicon.ico | Bin 0 -> 15086 bytes .../assets/img/favicons/manifest.json | 20 + .../assets/img/favicons/safari-pinned-tab.svg | 1 + .../assets/img/guides/bootstrap-parcel.png | Bin 0 -> 144652 bytes .../assets/img/guides/bootstrap-parcel@2x.png | Bin 0 -> 511984 bytes .../assets/img/guides/bootstrap-vite.png | Bin 0 -> 146772 bytes .../assets/img/guides/bootstrap-vite@2x.png | Bin 0 -> 517193 bytes .../assets/img/guides/bootstrap-webpack.png | Bin 0 -> 149510 bytes .../img/guides/bootstrap-webpack@2x.png | Bin 0 -> 532848 bytes .../guides/parcel-dev-server-bootstrap.png | Bin 0 -> 15565 bytes .../assets/img/guides/parcel-dev-server.png | Bin 0 -> 13345 bytes .../img/guides/vite-dev-server-bootstrap.png | Bin 0 -> 14001 bytes .../assets/img/guides/vite-dev-server.png | Bin 0 -> 13265 bytes .../guides/webpack-dev-server-bootstrap.png | Bin 0 -> 14702 bytes .../assets/img/guides/webpack-dev-server.png | Bin 0 -> 13999 bytes .../docs/[version]/assets/img/parcel.png | Bin 0 -> 6001 bytes .../static/docs/[version]/assets/img/vite.svg | 1 + .../docs/[version]/assets/img/webpack.svg | 1 + .../docs/[version]/assets/js/color-modes.js | 80 + .../[version]/assets/js/validate-forms.js | 19 + .../wwwroot/lib/bootstrap/site/static/sw.js | 27 + .../wwwroot/lib/bootstrap/site/tsconfig.json | 13 + .../jquery-validation-unobtrusive/.bower.json | 43 +- .../.gitattributes | 53 + .../lib/jquery-validation-unobtrusive/.npmrc | 1 + .../templates/default-build.yml | 159 + .../CODE-OF-CONDUCT.md | 6 + .../CONTRIBUTING.md | 4 + .../jquery-validation-unobtrusive/LICENSE.txt | 23 + ...osoft.jQuery.Unobtrusive.Validation.nuspec | 28 + .../jquery-validation-unobtrusive/README.md | 10 + .../jquery-validation-unobtrusive/Sign.proj | 69 + .../jquery-validation-unobtrusive/Sign.props | 52 + .../jquery-validation-unobtrusive/bower.json | 35 - .../jquery-validation-unobtrusive/build.cmd | 2 + .../jquery-validation-unobtrusive/build.proj | 58 + .../dependencies.props | 10 + .../jquery-validation-unobtrusive/gulpfile.js | 23 + .../jquery.validate.unobtrusive.min.js | 5 - .../nuget.config | 8 + .../package-lock.json | 7939 +++++++ .../package.json | 43 + .../lib/jquery-validation-unobtrusive/run.ps1 | 1 + .../{ => src}/jquery.validate.unobtrusive.js | 43 +- .../test/webpacktest/src/index.js | 1 + .../version.props | 1 + .../wwwroot/lib/jquery-validation/.bower.json | 17 +- .../lib/jquery-validation/CONTRIBUTING.md | 13 +- .../lib/jquery-validation/Gruntfile.js | 88 +- .../wwwroot/lib/jquery-validation/README.md | 68 +- .../wwwroot/lib/jquery-validation/SECURITY.md | 10 + .../wwwroot/lib/jquery-validation/bower.json | 6 +- .../lib/jquery-validation/build/release.js | 62 + .../lib/jquery-validation/changelog.md | 317 + .../dist/additional-methods.js | 1333 +- .../dist/additional-methods.min.js | 8 +- .../dist/jquery-validation-sri.json | 1172 + .../jquery-validation/dist/jquery.validate.js | 921 +- .../dist/jquery.validate.min.js | 8 +- .../dist/localization/messages_ar.js | 64 + .../dist/localization/messages_ar.min.js | 4 + .../dist/localization/messages_az.js | 35 + .../dist/localization/messages_az.min.js | 4 + .../dist/localization/messages_bg.js | 35 + .../dist/localization/messages_bg.min.js | 4 + .../dist/localization/messages_bn_BD.js | 35 + .../dist/localization/messages_bn_BD.min.js | 4 + .../dist/localization/messages_ca.js | 35 + .../dist/localization/messages_ca.min.js | 4 + .../dist/localization/messages_cs.js | 36 + .../dist/localization/messages_cs.min.js | 4 + .../dist/localization/messages_da.js | 46 + .../dist/localization/messages_da.min.js | 4 + .../dist/localization/messages_de.js | 82 + .../dist/localization/messages_de.min.js | 4 + .../dist/localization/messages_el.js | 35 + .../dist/localization/messages_el.min.js | 4 + .../dist/localization/messages_es.js | 38 + .../dist/localization/messages_es.min.js | 4 + .../dist/localization/messages_es_AR.js | 39 + .../dist/localization/messages_es_AR.min.js | 4 + .../dist/localization/messages_es_PE.js | 39 + .../dist/localization/messages_es_PE.min.js | 4 + .../dist/localization/messages_et.js | 33 + .../dist/localization/messages_et.min.js | 4 + .../dist/localization/messages_eu.js | 35 + .../dist/localization/messages_eu.min.js | 4 + .../dist/localization/messages_fa.js | 39 + .../dist/localization/messages_fa.min.js | 4 + .../dist/localization/messages_fi.js | 33 + .../dist/localization/messages_fi.min.js | 4 + .../dist/localization/messages_fr.js | 65 + .../dist/localization/messages_fr.min.js | 4 + .../dist/localization/messages_ge.js | 35 + .../dist/localization/messages_ge.min.js | 4 + .../dist/localization/messages_gl.js | 40 + .../dist/localization/messages_gl.min.js | 4 + .../dist/localization/messages_he.js | 35 + .../dist/localization/messages_he.min.js | 4 + .../dist/localization/messages_hi.js | 54 + .../dist/localization/messages_hi.min.js | 4 + .../dist/localization/messages_hr.js | 35 + .../dist/localization/messages_hr.min.js | 4 + .../dist/localization/messages_hu.js | 35 + .../dist/localization/messages_hu.min.js | 4 + .../dist/localization/messages_hy_AM.js | 35 + .../dist/localization/messages_hy_AM.min.js | 4 + .../dist/localization/messages_id.js | 34 + .../dist/localization/messages_id.min.js | 4 + .../dist/localization/messages_is.js | 33 + .../dist/localization/messages_is.min.js | 4 + .../dist/localization/messages_it.js | 39 + .../dist/localization/messages_it.min.js | 4 + .../dist/localization/messages_ja.js | 36 + .../dist/localization/messages_ja.min.js | 4 + .../dist/localization/messages_ka.js | 35 + .../dist/localization/messages_ka.min.js | 4 + .../dist/localization/messages_kk.js | 35 + .../dist/localization/messages_kk.min.js | 4 + .../dist/localization/messages_ko.js | 35 + .../dist/localization/messages_ko.min.js | 4 + .../dist/localization/messages_lt.js | 35 + .../dist/localization/messages_lt.min.js | 4 + .../dist/localization/messages_lv.js | 35 + .../dist/localization/messages_lv.min.js | 4 + .../dist/localization/messages_mk.js | 35 + .../dist/localization/messages_mk.min.js | 4 + .../dist/localization/messages_my.js | 35 + .../dist/localization/messages_my.min.js | 4 + .../dist/localization/messages_nl.js | 46 + .../dist/localization/messages_nl.min.js | 4 + .../dist/localization/messages_no.js | 35 + .../dist/localization/messages_no.min.js | 4 + .../dist/localization/messages_pl.js | 38 + .../dist/localization/messages_pl.min.js | 4 + .../dist/localization/messages_pt_BR.js | 91 + .../dist/localization/messages_pt_BR.min.js | 4 + .../dist/localization/messages_pt_PT.js | 39 + .../dist/localization/messages_pt_PT.min.js | 4 + .../dist/localization/messages_ro.js | 35 + .../dist/localization/messages_ro.min.js | 4 + .../dist/localization/messages_ru.js | 35 + .../dist/localization/messages_ru.min.js | 4 + .../dist/localization/messages_sd.js | 35 + .../dist/localization/messages_sd.min.js | 4 + .../dist/localization/messages_si.js | 35 + .../dist/localization/messages_si.min.js | 4 + .../dist/localization/messages_sk.js | 33 + .../dist/localization/messages_sk.min.js | 4 + .../dist/localization/messages_sl.js | 35 + .../dist/localization/messages_sl.min.js | 4 + .../dist/localization/messages_sr.js | 36 + .../dist/localization/messages_sr.min.js | 4 + .../dist/localization/messages_sr_lat.js | 36 + .../dist/localization/messages_sr_lat.min.js | 4 + .../dist/localization/messages_sv.js | 35 + .../dist/localization/messages_sv.min.js | 4 + .../dist/localization/messages_th.js | 35 + .../dist/localization/messages_th.min.js | 4 + .../dist/localization/messages_tj.js | 35 + .../dist/localization/messages_tj.min.js | 4 + .../dist/localization/messages_tr.js | 37 + .../dist/localization/messages_tr.min.js | 4 + .../dist/localization/messages_uk.js | 35 + .../dist/localization/messages_uk.min.js | 4 + .../dist/localization/messages_ur.js | 35 + .../dist/localization/messages_ur.min.js | 4 + .../dist/localization/messages_vi.js | 35 + .../dist/localization/messages_vi.min.js | 4 + .../dist/localization/messages_zh.js | 36 + .../dist/localization/messages_zh.min.js | 4 + .../dist/localization/messages_zh_TW.js | 37 + .../dist/localization/messages_zh_TW.min.js | 4 + .../dist/localization/methods_de.js | 24 + .../dist/localization/methods_de.min.js | 4 + .../dist/localization/methods_es_CL.js | 24 + .../dist/localization/methods_es_CL.min.js | 4 + .../dist/localization/methods_fi.js | 24 + .../dist/localization/methods_fi.min.js | 4 + .../dist/localization/methods_it.js | 24 + .../dist/localization/methods_it.min.js | 4 + .../dist/localization/methods_nl.js | 24 + .../dist/localization/methods_nl.min.js | 4 + .../dist/localization/methods_pt.js | 21 + .../dist/localization/methods_pt.min.js | 4 + .../lib/jquery-validation/package.json | 42 +- .../src/additional/abaRoutingNumber.js | 31 + .../src/additional/accept.js | 34 +- .../src/additional/additional.js | 36 +- .../src/additional/alphanumeric.js | 6 +- .../src/additional/bankaccountNL.js | 15 +- .../src/additional/bankorgiroaccountNL.js | 10 +- .../jquery-validation/src/additional/bic.js | 10 +- .../jquery-validation/src/additional/cifES.js | 137 +- .../jquery-validation/src/additional/cnhBR.js | 49 + .../src/additional/cnpjBR.js | 74 + .../jquery-validation/src/additional/cpfBR.js | 38 +- .../src/additional/creditcard.js | 40 + .../src/additional/creditcardtypes.js | 46 +- .../src/additional/currency.js | 14 +- .../src/additional/dateFA.js | 6 +- .../src/additional/dateITA.js | 20 +- .../src/additional/dateNL.js | 6 +- .../src/additional/extension.js | 8 +- .../src/additional/giroaccountNL.js | 6 +- .../src/additional/greaterThan.js | 11 + .../src/additional/greaterThanEqual.js | 11 + .../jquery-validation/src/additional/iban.js | 60 +- .../src/additional/integer.js | 6 +- .../jquery-validation/src/additional/ipv4.js | 6 +- .../jquery-validation/src/additional/ipv6.js | 6 +- .../src/additional/lessThan.js | 11 + .../src/additional/lessThanEqual.js | 11 + .../src/additional/lettersonly.js | 6 +- .../src/additional/letterswithbasicpunc.js | 6 +- .../src/additional/maxfiles.js | 14 + .../src/additional/maxsize.js | 18 + .../src/additional/maxsizetotal.js | 22 + .../src/additional/mobileNL.js | 6 +- .../src/additional/mobileRU.js | 4 + .../src/additional/mobileUK.js | 10 +- .../src/additional/netmask.js | 3 + .../jquery-validation/src/additional/nieES.js | 49 +- .../jquery-validation/src/additional/nifES.js | 11 +- .../jquery-validation/src/additional/nipPL.js | 22 + .../jquery-validation/src/additional/nisBR.js | 57 + .../src/additional/notEqualTo.js | 4 +- .../src/additional/nowhitespace.js | 6 +- .../src/additional/pattern.js | 12 +- .../src/additional/phoneNL.js | 6 +- .../src/additional/phonePL.js | 23 + .../src/additional/phoneUK.js | 10 +- .../src/additional/phoneUS.js | 12 +- .../src/additional/phonesUK.js | 13 +- .../src/additional/postalCodeCA.js | 4 +- .../src/additional/postalcodeBR.js | 6 +- .../src/additional/postalcodeIT.js | 6 +- .../src/additional/postalcodeNL.js | 6 +- .../src/additional/postcodeUK.js | 6 +- .../src/additional/require_from_group.js | 30 +- .../src/additional/skip_or_fill_minimum.js | 32 +- .../src/additional/statesUS.js | 18 +- .../src/additional/strippedminlength.js | 6 +- .../jquery-validation/src/additional/time.js | 6 +- .../src/additional/time12h.js | 6 +- .../jquery-validation/src/additional/url2.js | 8 +- .../jquery-validation/src/additional/vinUS.js | 73 +- .../src/additional/zipcodeUS.js | 6 +- .../src/additional/ziprange.js | 6 +- .../wwwroot/lib/jquery-validation/src/ajax.js | 33 +- .../wwwroot/lib/jquery-validation/src/core.js | 880 +- .../src/localization/messages_ar.js | 45 +- .../src/localization/messages_az.js | 23 + .../src/localization/messages_bg.js | 16 +- .../src/localization/messages_bn_BD.js | 16 +- .../src/localization/messages_ca.js | 18 +- .../src/localization/messages_cs.js | 17 +- .../src/localization/messages_da.js | 32 +- .../src/localization/messages_de.js | 74 +- .../src/localization/messages_el.js | 16 +- .../src/localization/messages_es.js | 16 +- .../src/localization/messages_es_AR.js | 16 +- .../src/localization/messages_es_PE.js | 16 +- .../src/localization/messages_et.js | 16 +- .../src/localization/messages_eu.js | 16 +- .../src/localization/messages_fa.js | 33 +- .../src/localization/messages_fi.js | 16 +- .../src/localization/messages_fr.js | 32 +- .../src/localization/messages_ge.js | 8 +- .../src/localization/messages_gl.js | 20 +- .../src/localization/messages_he.js | 16 +- .../src/localization/messages_hi.js | 42 + .../src/localization/messages_hr.js | 16 +- .../src/localization/messages_hu.js | 19 +- .../src/localization/messages_hy_AM.js | 16 +- .../src/localization/messages_id.js | 16 +- .../src/localization/messages_is.js | 16 +- .../src/localization/messages_it.js | 46 +- .../src/localization/messages_ja.js | 17 +- .../src/localization/messages_ka.js | 16 +- .../src/localization/messages_kk.js | 16 +- .../src/localization/messages_ko.js | 16 +- .../src/localization/messages_lt.js | 16 +- .../src/localization/messages_lv.js | 16 +- .../src/localization/messages_mk.js | 23 + .../src/localization/messages_my.js | 16 +- .../src/localization/messages_nl.js | 19 +- .../src/localization/messages_no.js | 26 +- .../src/localization/messages_pl.js | 19 +- .../src/localization/messages_pt_BR.js | 74 +- .../src/localization/messages_pt_PT.js | 16 +- .../src/localization/messages_ro.js | 18 +- .../src/localization/messages_ru.js | 16 +- .../src/localization/messages_sd.js | 23 + .../src/localization/messages_si.js | 16 +- .../src/localization/messages_sk.js | 23 +- .../src/localization/messages_sl.js | 16 +- .../src/localization/messages_sr.js | 17 +- .../src/localization/messages_sr_lat.js | 19 +- .../src/localization/messages_sv.js | 20 +- .../src/localization/messages_th.js | 16 +- .../src/localization/messages_tj.js | 18 +- .../src/localization/messages_tr.js | 21 +- .../src/localization/messages_uk.js | 16 +- .../src/localization/messages_ur.js | 23 + .../src/localization/messages_vi.js | 16 +- .../src/localization/messages_zh.js | 17 +- .../src/localization/messages_zh_TW.js | 17 +- .../src/localization/methods_de.js | 12 +- .../src/localization/methods_es_CL.js | 12 +- .../src/localization/methods_fi.js | 12 +- .../src/localization/methods_it.js | 12 + .../src/localization/methods_nl.js | 11 +- .../src/localization/methods_pt.js | 8 +- .../jquery-validation/validation.jquery.json | 8 +- .../wwwroot/lib/jquery/.bower.json | 28 +- .../wwwroot/lib/jquery/AUTHORS.txt | 371 + .../jquery/{MIT-LICENSE.txt => LICENSE.txt} | 3 +- .../wwwroot/lib/jquery/README.md | 60 + .../wwwroot/lib/jquery/bower.json | 18 +- .../wwwroot/lib/jquery/dist/jquery.js | 9180 ++++--- .../wwwroot/lib/jquery/dist/jquery.min.js | 7 +- .../wwwroot/lib/jquery/dist/jquery.min.map | 2 +- .../wwwroot/lib/jquery/dist/jquery.slim.js | 8617 +++++++ .../lib/jquery/dist/jquery.slim.min.js | 2 + .../lib/jquery/dist/jquery.slim.min.map | 1 + .../wwwroot/lib/jquery/src/ajax.js | 328 +- .../wwwroot/lib/jquery/src/ajax/jsonp.js | 50 +- .../wwwroot/lib/jquery/src/ajax/load.js | 50 +- .../wwwroot/lib/jquery/src/ajax/parseJSON.js | 13 - .../wwwroot/lib/jquery/src/ajax/parseXML.js | 28 - .../wwwroot/lib/jquery/src/ajax/script.js | 50 +- .../lib/jquery/src/ajax/var/location.js | 5 + .../wwwroot/lib/jquery/src/ajax/var/nonce.js | 10 +- .../wwwroot/lib/jquery/src/ajax/var/rquery.js | 8 +- .../wwwroot/lib/jquery/src/ajax/xhr.js | 124 +- .../wwwroot/lib/jquery/src/attributes.js | 6 +- .../wwwroot/lib/jquery/src/attributes/attr.js | 122 +- .../lib/jquery/src/attributes/classes.js | 194 +- .../wwwroot/lib/jquery/src/attributes/prop.js | 112 +- .../lib/jquery/src/attributes/support.js | 24 +- .../wwwroot/lib/jquery/src/attributes/val.js | 112 +- .../wwwroot/lib/jquery/src/callbacks.js | 231 +- .../wwwroot/lib/jquery/src/core.js | 372 +- .../wwwroot/lib/jquery/src/core/DOMEval.js | 43 + .../wwwroot/lib/jquery/src/core/access.js | 44 +- .../wwwroot/lib/jquery/src/core/camelCase.js | 23 + .../wwwroot/lib/jquery/src/core/init.js | 70 +- .../wwwroot/lib/jquery/src/core/isAttached.js | 26 + .../wwwroot/lib/jquery/src/core/nodeName.js | 13 + .../wwwroot/lib/jquery/src/core/parseHTML.js | 52 +- .../wwwroot/lib/jquery/src/core/parseXML.js | 35 + .../lib/jquery/src/core/ready-no-deferred.js | 97 + .../wwwroot/lib/jquery/src/core/ready.js | 93 +- .../lib/jquery/src/core/readyException.js | 13 + .../lib/jquery/src/core/stripAndCollapse.js | 14 + .../wwwroot/lib/jquery/src/core/support.js | 20 + .../wwwroot/lib/jquery/src/core/toType.js | 20 + .../wwwroot/lib/jquery/src/core/var/rhtml.js | 7 + .../lib/jquery/src/core/var/rsingleTag.js | 11 +- .../wwwroot/lib/jquery/src/css.js | 513 +- .../lib/jquery/src/css/addGetHookIf.js | 10 +- .../wwwroot/lib/jquery/src/css/adjustCSS.js | 74 + .../wwwroot/lib/jquery/src/css/curCSS.js | 73 +- .../lib/jquery/src/css/defaultDisplay.js | 70 - .../lib/jquery/src/css/finalPropName.js | 42 + .../jquery/src/css/hiddenVisibleSelectors.js | 16 +- .../wwwroot/lib/jquery/src/css/showHide.js | 105 + .../wwwroot/lib/jquery/src/css/support.js | 198 +- .../lib/jquery/src/css/var/cssExpand.js | 6 +- .../lib/jquery/src/css/var/getStyles.js | 17 +- .../lib/jquery/src/css/var/isHidden.js | 13 - .../jquery/src/css/var/isHiddenWithinTree.js | 34 + .../lib/jquery/src/css/var/rboxStyle.js | 7 + .../lib/jquery/src/css/var/rcustomProp.js | 7 + .../wwwroot/lib/jquery/src/css/var/rmargin.js | 3 - .../lib/jquery/src/css/var/rnumnonpx.js | 6 +- .../lib/jquery/src/css/{ => var}/swap.js | 14 +- .../wwwroot/lib/jquery/src/data.js | 134 +- .../wwwroot/lib/jquery/src/data/Data.js | 191 +- .../data/{accepts.js => var/acceptData.js} | 13 +- .../data/var/{data_user.js => dataPriv.js} | 6 +- .../data/var/{data_priv.js => dataUser.js} | 6 +- .../wwwroot/lib/jquery/src/deferred.js | 419 +- .../lib/jquery/src/deferred/exceptionHook.js | 25 + .../wwwroot/lib/jquery/src/deprecated.js | 92 +- .../jquery/src/deprecated/ajax-event-alias.js | 22 + .../lib/jquery/src/deprecated/event.js | 52 + .../wwwroot/lib/jquery/src/dimensions.js | 34 +- .../wwwroot/lib/jquery/src/effects.js | 494 +- .../wwwroot/lib/jquery/src/effects/Tween.js | 31 +- .../jquery/src/effects/animatedSelector.js | 12 +- .../wwwroot/lib/jquery/src/event.js | 1014 +- .../wwwroot/lib/jquery/src/event/ajax.js | 13 - .../wwwroot/lib/jquery/src/event/alias.js | 39 - .../wwwroot/lib/jquery/src/event/support.js | 9 - .../wwwroot/lib/jquery/src/event/trigger.js | 199 + .../wwwroot/lib/jquery/src/exports/amd.js | 8 +- .../wwwroot/lib/jquery/src/exports/global.js | 18 +- .../wwwroot/lib/jquery/src/intro.js | 44 - .../wwwroot/lib/jquery/src/jquery.js | 11 +- .../wwwroot/lib/jquery/src/manipulation.js | 552 +- .../lib/jquery/src/manipulation/_evalUrl.js | 26 +- .../jquery/src/manipulation/buildFragment.js | 106 + .../lib/jquery/src/manipulation/getAll.js | 32 + .../jquery/src/manipulation/setGlobalEval.js | 22 + .../lib/jquery/src/manipulation/support.js | 29 +- .../src/manipulation/var/rcheckableType.js | 3 - .../src/manipulation/var/rscriptType.js | 5 + .../jquery/src/manipulation/var/rtagName.js | 8 + .../lib/jquery/src/manipulation/wrapMap.js | 30 + .../wwwroot/lib/jquery/src/offset.js | 155 +- .../wwwroot/lib/jquery/src/outro.js | 1 - .../wwwroot/lib/jquery/src/queue.js | 49 +- .../wwwroot/lib/jquery/src/queue/delay.js | 13 +- .../wwwroot/lib/jquery/src/selector-native.js | 248 +- .../wwwroot/lib/jquery/src/selector-sizzle.js | 14 - .../wwwroot/lib/jquery/src/selector.js | 2118 +- .../lib/jquery/src/selector/contains.js | 21 + .../lib/jquery/src/selector/escapeSelector.js | 31 + .../wwwroot/lib/jquery/src/serialize.js | 95 +- .../lib/jquery/src/sizzle/dist/sizzle.js | 2067 -- .../lib/jquery/src/sizzle/dist/sizzle.min.js | 3 - .../lib/jquery/src/sizzle/dist/sizzle.min.map | 1 - .../wwwroot/lib/jquery/src/traversing.js | 137 +- .../lib/jquery/src/traversing/findFilter.js | 69 +- .../lib/jquery/src/traversing/var/dir.js | 22 + .../src/traversing/var/rneedsContext.js | 6 +- .../lib/jquery/src/traversing/var/siblings.js | 17 + .../jquery/src/var/ObjectFunctionString.js | 7 + .../wwwroot/lib/jquery/src/var/arr.js | 6 +- .../wwwroot/lib/jquery/src/var/class2type.js | 6 +- .../wwwroot/lib/jquery/src/var/concat.js | 5 - .../wwwroot/lib/jquery/src/var/document.js | 5 + .../lib/jquery/src/var/documentElement.js | 7 + .../wwwroot/lib/jquery/src/var/flat.js | 16 + .../wwwroot/lib/jquery/src/var/fnToString.js | 7 + .../wwwroot/lib/jquery/src/var/getProto.js | 5 + .../wwwroot/lib/jquery/src/var/hasOwn.js | 6 +- .../wwwroot/lib/jquery/src/var/indexOf.js | 6 +- .../wwwroot/lib/jquery/src/var/isFunction.js | 17 + .../wwwroot/lib/jquery/src/var/isWindow.js | 8 + .../wwwroot/lib/jquery/src/var/pnum.js | 8 +- .../wwwroot/lib/jquery/src/var/pop.js | 9 + .../wwwroot/lib/jquery/src/var/push.js | 6 +- .../lib/jquery/src/var/rcheckableType.js | 5 + .../wwwroot/lib/jquery/src/var/rcssNum.js | 9 + .../lib/jquery/src/var/rnothtmlwhite.js | 8 + .../wwwroot/lib/jquery/src/var/rnotwhite.js | 3 - .../wwwroot/lib/jquery/src/var/rtrimCSS.js | 12 + .../wwwroot/lib/jquery/src/var/slice.js | 6 +- .../wwwroot/lib/jquery/src/var/sort.js | 9 + .../wwwroot/lib/jquery/src/var/splice.js | 9 + .../lib/jquery/src/var/strundefined.js | 3 - .../wwwroot/lib/jquery/src/var/support.js | 6 +- .../wwwroot/lib/jquery/src/var/toString.js | 6 +- .../wwwroot/lib/jquery/src/var/whitespace.js | 8 + .../wwwroot/lib/jquery/src/wrap.js | 57 +- 1375 files changed, 222481 insertions(+), 33269 deletions(-) rename .github/workflows/{dotnet.yml => buildAndTest.yml} (97%) delete mode 100644 .github/workflows/main.yml create mode 100644 contrib/yavsc.service create mode 100644 src/Yavsc.Server/Migrations/20250613122253_notificationTarget.Designer.cs create mode 100644 src/Yavsc.Server/Migrations/20250613122253_notificationTarget.cs create mode 100644 src/Yavsc.Server/Migrations/20250613123306_notificationNulls.Designer.cs create mode 100644 src/Yavsc.Server/Migrations/20250613123306_notificationNulls.cs create mode 100644 src/Yavsc.Server/Migrations/20250613131533_trackedNulls.Designer.cs create mode 100644 src/Yavsc.Server/Migrations/20250613131533_trackedNulls.cs create mode 100644 src/Yavsc.Server/Migrations/20250613131836_blogNulls.Designer.cs create mode 100644 src/Yavsc.Server/Migrations/20250613131836_blogNulls.cs create mode 100644 src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.Designer.cs create mode 100644 src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.cs create mode 100644 src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.Designer.cs create mode 100644 src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.cs create mode 100644 "src/Yavsc/\"BlogSpot\"" create mode 100644 src/Yavsc/data/key-afbdf233-abc3-4762-865b-884187518d95.xml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.babelrc.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.browserslistrc create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bundlewatch.config.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.cspell.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.editorconfig create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintignore create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintrc.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.gitattributes create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CODEOWNERS create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CONTRIBUTING.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/config.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/SUPPORT.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/codeql/codeql-config.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/dependabot.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/release-drafter.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/browserstack.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/bundlewatch.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/calibreapp-image-actions.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/codeql.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/cspell.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/css.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/docs.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-close-require.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-labeled.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/js.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/lint.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/node-sass.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/release-notes.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.prettierignore create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintignore create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintrc.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/CODE_OF_CONDUCT.md delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/Gruntfile.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/SECURITY.md delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/bower.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/banner.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/build-plugins.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/change-version.mjs create mode 100755 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/docs-prep.sh create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/generate-sri.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/postcss.config.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/rollup.config.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/vnu-jar.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/zip-examples.mjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/composer.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/config.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/dist/js/npm.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.svg delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/.jshintrc delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/bs-commonjs-generator.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/bs-glyphicons-data-generator.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/bs-lessdoc-parser.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/bs-raw-files-generator.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/configBridge.json delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/grunt/sauce_browsers.yml delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/.jscsrc delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/.jshintrc delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/affix.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/alert.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/button.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/carousel.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/collapse.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/alert.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/alert.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/base-component.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/base-component.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/button.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/button.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/carousel.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/carousel.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/collapse.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/collapse.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/data.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/data.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/event-handler.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/event-handler.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/manipulator.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/manipulator.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/selector-engine.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dom/selector-engine.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dropdown.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/dropdown.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/modal.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/modal.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/offcanvas.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/offcanvas.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/popover.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/popover.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/scrollspy.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/scrollspy.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/tab.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/tab.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/toast.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/toast.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/tooltip.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/tooltip.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/backdrop.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/backdrop.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/component-functions.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/component-functions.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/config.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/config.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/focustrap.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/focustrap.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/index.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/index.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/sanitizer.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/sanitizer.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/scrollbar.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/scrollbar.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/swipe.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/swipe.js.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/template-factory.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dist/util/template-factory.js.map delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/dropdown.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/index.esm.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/index.umd.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/modal.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/popover.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/scrollspy.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/alert.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/base-component.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/button.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/carousel.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/collapse.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/dom/data.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/dom/event-handler.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/dom/manipulator.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/dom/selector-engine.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/dropdown.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/modal.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/offcanvas.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/popover.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/scrollspy.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/tab.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/toast.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/tooltip.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/backdrop.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/component-functions.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/config.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/focustrap.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/index.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/sanitizer.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/scrollbar.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/swipe.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/src/util/template-factory.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tab.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/README.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/browsers.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/helpers/fixture.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/bundle-modularity.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/bundle.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/index.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle-modularity.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/karma.conf.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/alert.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/base-component.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/button.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/carousel.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/collapse.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/data.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/event-handler.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/manipulator.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/selector-engine.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dropdown.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/jquery.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/modal.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/offcanvas.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/popover.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/scrollspy.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tab.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/toast.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tooltip.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/backdrop.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/component-functions.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/config.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/focustrap.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/index.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/sanitizer.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/scrollbar.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/swipe.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/template-factory.spec.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/alert.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/button.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/carousel.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/collapse.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/dropdown.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/floating-label.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/input.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/modal.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/popover.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/scrollspy.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tab.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/toast.html create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tooltip.html delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tooltip.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/transition.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csscomb.json delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csslintrc delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/alerts.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/badges.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/bootstrap.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/breadcrumbs.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/button-groups.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/buttons.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/carousel.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/close.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/code.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/component-animations.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/dropdowns.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/forms.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/glyphicons.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/grid.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/input-groups.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/jumbotron.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/labels.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/list-group.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/media.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/alerts.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/background-variant.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/border-radius.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/buttons.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/center-block.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/clearfix.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/forms.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/gradients.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/grid-framework.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/grid.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/hide-text.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/image.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/labels.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/list-group.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/nav-divider.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/nav-vertical-align.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/opacity.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/pagination.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/panels.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/progress-bar.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/reset-filter.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/responsive-visibility.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/size.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/tab-focus.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/table-row.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/text-emphasis.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/mixins/vendor-prefixes.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/modals.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/navbar.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/navs.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/normalize.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/pager.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/pagination.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/panels.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/popovers.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/print.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/progress-bars.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/responsive-embed.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/responsive-utilities.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/scaffolding.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/tables.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/theme.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/thumbnails.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/tooltip.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/type.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/utilities.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/variables.less delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/wells.less create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/nuget/MyGet.ps1 create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/nuget/bootstrap.nuspec create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/nuget/bootstrap.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/nuget/bootstrap.sass.nuspec create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/package-lock.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_accordion.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_alert.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_badge.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_breadcrumb.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_button-group.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_buttons.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_card.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_carousel.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_close.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_containers.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_dropdown.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_forms.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_functions.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_grid.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_helpers.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_images.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_list-group.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_maps.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_mixins.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_modal.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_nav.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_navbar.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_offcanvas.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_pagination.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_placeholders.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_popover.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_progress.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_reboot.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_root.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_spinners.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_tables.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_toasts.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_tooltip.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_transitions.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_type.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_utilities.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_variables-dark.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/_variables.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/bootstrap-grid.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/bootstrap-reboot.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/bootstrap-utilities.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/bootstrap.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_floating-labels.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_form-check.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_form-control.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_form-range.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_form-select.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_form-text.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_input-group.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_labels.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/forms/_validation.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_clearfix.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_color-bg.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_colored-links.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_focus-ring.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_icon-link.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_position.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_ratio.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_stacks.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_stretched-link.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_text-truncation.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_visually-hidden.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/helpers/_vr.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_alert.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_backdrop.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_banner.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_border-radius.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_box-shadow.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_breakpoints.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_buttons.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_caret.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_clearfix.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_color-mode.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_color-scheme.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_container.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_deprecate.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_forms.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_gradients.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_grid.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_image.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_list-group.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_lists.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_pagination.scss rename src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/{less/mixins/reset-text.less => scss/mixins/_reset-text.scss} (60%) rename src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/{less/mixins/resize.less => scss/mixins/_resize.scss} (54%) create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_table-variants.scss rename src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/{less/mixins/text-overflow.less => scss/mixins/_text-truncate.scss} (75%) create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_transition.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_utilities.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/mixins/_visually-hidden.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/jasmine.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/mixins/_color-modes.test.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/mixins/_utilities.test.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/sass-true/register.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/sass-true/runner.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/tests/utilities/_api.test.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/utilities/_api.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/scss/vendor/_rfs.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/.prettierrc.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/astro.config.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/breakpoints.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/colors.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/core-team.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/docs-versions.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/examples.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/grays.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/icons.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/plugins.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/sidebar.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/theme-colors.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/data/translations.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/postcss.config.cjs create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/application.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/album-rtl/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/album/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/badges/badges.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/badges/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/blog-rtl/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/blog/blog.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/blog/blog.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/blog/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/breadcrumbs/breadcrumbs.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/breadcrumbs/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/buttons/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/carousel-rtl/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/carousel/carousel.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/carousel/carousel.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/carousel/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet-rtl/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout-rtl/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/cover.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/dashboard.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.rtl.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/dropdowns.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/features.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-1.jpg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-2.jpg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-3.jpg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/footers/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/grid.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/headers.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/bootstrap-docs.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/bootstrap-themes.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/heroes.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotron/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/jumbotrons.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/list-groups.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/masonry/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/modals.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-bottom/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/navbar-fixed.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/navbar-static.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/navbars-offcanvas.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/navbars.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/pricing.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/product.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/sign-in.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/starter-template/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/sticky-footer-navbar.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/sticky-footer.css create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/sidebar.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/snippets.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/search.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/snippets.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/stackblitz.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Ads.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/DocsSidebar.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Scripts.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/TableOfContents.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/footer/Footer.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Analytics.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Favicons.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Head.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Scss.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Social.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Stylesheet.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Header.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/LinkItem.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Navigation.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Skippy.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Versions.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/CSSVariables.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/ComponentUtilities.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Customize.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/GetStarted.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Icons.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/MastHead.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Plugins.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Themes.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/BootstrapWhiteFillIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/CircleSquareIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/DropletFillIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/GitHubIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/HamburgerIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/OpenCollectiveIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/Symbols.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/XIcon.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/AddedIn.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/BsTable.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Callout.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/CalloutDeprecatedDarkVariants.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Code.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/DeprecatedIn.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Example.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/GuideFooter.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDataAttributes.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDismiss.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDocs.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Placeholder.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/ScssDocs.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Table.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/TableContent.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/danger-async-methods.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-mediaqueries-breakpoints.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-npm-starter.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-prefersreducedmotion.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-sanitizer.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-color-assistive-technologies.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-data-bs-title-vs-title.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-input-support.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/config.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/brand.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/license.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/overview.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/team.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/translations.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/accordion.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/alerts.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/badge.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/breadcrumb.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/button-group.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/buttons.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/card.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/carousel.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/close-button.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/collapse.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/dropdowns.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/list-group.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/modal.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/navbar.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/navs-tabs.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/offcanvas.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/pagination.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/placeholders.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/popovers.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/progress.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/scrollspy.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/spinners.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/toasts.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/tooltips.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/content/figures.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/content/images.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/content/reboot.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/content/tables.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/content/typography.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color-modes.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/components.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/css-variables.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/optimize.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/options.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/overview.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/sass.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/docsref.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/extend/approach.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/extend/icons.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/checks-radios.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/floating-labels.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/form-control.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/input-group.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/layout.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/overview.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/range.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/select.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/forms/validation.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/accessibility.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/best-practices.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/browsers-devices.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/contents.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/contribute.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/download.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/introduction.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/javascript.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/parcel.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/rfs.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/rtl.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/vite.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/getting-started/webpack.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/clearfix.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/color-background.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/colored-links.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/focus-ring.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/icon-link.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/position.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/ratio.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/stacks.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/stretched-link.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/text-truncation.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/vertical-rule.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/helpers/visually-hidden.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/breakpoints.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/columns.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/containers.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/css-grid.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/grid.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/gutters.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/utilities.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/layout/z-index.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/migration.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/api.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/background.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/borders.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/colors.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/display.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/flex.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/float.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/interactions.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/link.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/object-fit.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/opacity.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/overflow.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/position.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/shadows.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/sizing.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/spacing.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/text.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/vertical-align.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/visibility.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/utilities/z-index.mdx create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/env.d.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/BaseLayout.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/DocsLayout.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/ExamplesLayout.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/RedirectLayout.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/SingleLayout.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/partials/BsThemes.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/partials/ExamplesMain.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/partials/Icons.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/partials/ResponsiveImage.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/layouts/partials/ThemeToggler.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/astro.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/bootstrap.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/config.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/content.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/data.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/examples.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/icon.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/image.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/layout.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/path.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/placeholder.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/prism.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/rehype.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/remark.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/toc.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/utils.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/libs/validation.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/404.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/[...alias].astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/[version]/[...slug].astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/[version]/examples/[...asset].ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/[version]/examples/[...example].astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/[version]/examples/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/[version]/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/docs/versions.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/examples.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/index.astro create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/pages/robots.txt.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/plugins/algolia-plugin.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/plugins/stackblitz-plugin.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_ads.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_anchor.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_brand.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_buttons.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_callouts.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_clipboard-js.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_colors.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_component-examples.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_content.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_footer.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_layout.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_masthead.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_navbar.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_placeholder-img.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_scrolling.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_search.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_sidebar.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_skippy.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_syntax.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_toc.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/_variables.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/docs.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/scss/docs_search.scss create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/types/auto-import.d.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/types/window.d.ts create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/CNAME create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/brand/bootstrap-logo-black.svg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/brand/bootstrap-logo-shadow.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/brand/bootstrap-logo-shadow@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/brand/bootstrap-logo-white.svg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/brand/bootstrap-logo.svg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/brand/bootstrap-social.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/bootstrap-icons.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/bootstrap-icons@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/bootstrap-themes-collage.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/bootstrap-themes-collage@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/bootstrap-themes.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/bootstrap-themes@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/album-rtl.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/album-rtl@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/album.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/album@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/badges.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/badges@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/blog-rtl.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/blog-rtl@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/blog.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/blog@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/breadcrumbs.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/breadcrumbs@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/buttons.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/buttons@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/carousel-rtl.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/carousel-rtl@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/carousel.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/carousel@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/cheatsheet-rtl.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/cheatsheet-rtl@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/cheatsheet.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/cheatsheet@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/checkout-rtl.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/checkout-rtl@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/checkout.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/checkout@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/cover.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/cover@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/dashboard-rtl.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/dashboard-rtl@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/dashboard.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/dashboard@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/dropdowns.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/dropdowns@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/features.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/features@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/footers.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/footers@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/grid.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/grid@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/headers.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/headers@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/heroes.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/heroes@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/jumbotron.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/jumbotron@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/jumbotrons.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/jumbotrons@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/list-groups.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/list-groups@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/masonry.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/masonry@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/modals.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/modals@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbar-bottom.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbar-bottom@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbar-fixed.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbar-fixed@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbar-static.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbar-static@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbars-offcanvas.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbars-offcanvas@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbars.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/navbars@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/offcanvas-navbar.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/offcanvas-navbar@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/pricing.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/pricing@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/product.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/product@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sidebars.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sidebars@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sign-in.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sign-in@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/starter-template.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/starter-template@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sticky-footer-navbar.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sticky-footer-navbar@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sticky-footer.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/examples/sticky-footer@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/android-chrome-192x192.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/android-chrome-512x512.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/apple-touch-icon.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/favicon-16x16.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/favicon-32x32.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/favicon.ico create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/manifest.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/favicons/safari-pinned-tab.svg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/bootstrap-parcel.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/bootstrap-parcel@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/bootstrap-vite.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/bootstrap-vite@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/bootstrap-webpack.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/bootstrap-webpack@2x.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/parcel-dev-server-bootstrap.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/parcel-dev-server.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/vite-dev-server-bootstrap.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/vite-dev-server.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/webpack-dev-server-bootstrap.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/guides/webpack-dev-server.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/parcel.png create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/vite.svg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/img/webpack.svg create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/js/color-modes.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/docs/[version]/assets/js/validate-forms.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/static/sw.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/tsconfig.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/.gitattributes create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/.npmrc create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/.vsts-pipelines/templates/default-build.yml create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/CODE-OF-CONDUCT.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/CONTRIBUTING.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/Microsoft.jQuery.Unobtrusive.Validation.nuspec create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/README.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/Sign.proj create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/Sign.props delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/bower.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/build.cmd create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/build.proj create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/dependencies.props create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/gulpfile.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/nuget.config create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/package-lock.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/package.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/run.ps1 rename src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/{ => src}/jquery.validate.unobtrusive.js (93%) create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/test/webpacktest/src/index.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation-unobtrusive/version.props create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/SECURITY.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/build/release.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/jquery-validation-sri.json create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ar.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ar.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_az.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_az.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_bg.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_bg.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_bn_BD.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_bn_BD.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ca.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ca.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_cs.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_cs.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_da.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_da.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_de.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_de.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_el.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_el.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_es.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_es.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_es_AR.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_es_AR.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_es_PE.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_es_PE.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_et.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_et.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_eu.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_eu.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_fa.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_fa.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_fi.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_fi.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_fr.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_fr.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ge.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ge.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_gl.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_gl.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_he.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_he.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hi.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hi.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hr.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hr.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hu.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hu.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hy_AM.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_hy_AM.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_id.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_id.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_is.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_is.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_it.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_it.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ja.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ja.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ka.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ka.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_kk.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_kk.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ko.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ko.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_lt.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_lt.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_lv.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_lv.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_mk.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_mk.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_my.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_my.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_nl.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_nl.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_no.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_no.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_pl.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_pl.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_pt_BR.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_pt_BR.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_pt_PT.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_pt_PT.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ro.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ro.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ru.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ru.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sd.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sd.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_si.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_si.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sk.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sk.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sl.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sl.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sr.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sr.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sr_lat.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sr_lat.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sv.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_sv.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_th.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_th.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_tj.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_tj.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_tr.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_tr.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_uk.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_uk.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ur.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_ur.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_vi.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_vi.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_zh.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_zh.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_zh_TW.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/messages_zh_TW.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_de.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_de.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_es_CL.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_es_CL.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_fi.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_fi.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_it.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_it.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_nl.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_nl.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_pt.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/dist/localization/methods_pt.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/abaRoutingNumber.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/cnhBR.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/cnpjBR.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/creditcard.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/greaterThan.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/greaterThanEqual.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/lessThan.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/lessThanEqual.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/maxfiles.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/maxsize.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/maxsizetotal.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/mobileRU.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/netmask.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/nipPL.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/nisBR.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/additional/phonePL.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/localization/messages_az.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/localization/messages_hi.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/localization/messages_mk.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/localization/messages_sd.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/localization/messages_ur.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery-validation/src/localization/methods_it.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/AUTHORS.txt rename src/sampleWebAsWebApiClient/wwwroot/lib/jquery/{MIT-LICENSE.txt => LICENSE.txt} (93%) create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/README.md create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/dist/jquery.slim.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/dist/jquery.slim.min.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/dist/jquery.slim.min.map delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/ajax/parseJSON.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/ajax/parseXML.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/ajax/var/location.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/DOMEval.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/camelCase.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/isAttached.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/nodeName.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/parseXML.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/ready-no-deferred.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/readyException.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/stripAndCollapse.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/support.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/toType.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/core/var/rhtml.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/adjustCSS.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/defaultDisplay.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/finalPropName.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/showHide.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/var/isHidden.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/var/isHiddenWithinTree.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/var/rboxStyle.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/var/rcustomProp.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/var/rmargin.js rename src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/css/{ => var}/swap.js (69%) rename src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/data/{accepts.js => var/acceptData.js} (65%) rename src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/data/var/{data_user.js => dataPriv.js} (63%) rename src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/data/var/{data_priv.js => dataUser.js} (63%) create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/deferred/exceptionHook.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/deprecated/ajax-event-alias.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/deprecated/event.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/event/ajax.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/event/alias.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/event/support.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/event/trigger.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/intro.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/buildFragment.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/getAll.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/setGlobalEval.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/var/rcheckableType.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/var/rscriptType.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/var/rtagName.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/manipulation/wrapMap.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/outro.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/selector-sizzle.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/selector/contains.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/selector/escapeSelector.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/sizzle/dist/sizzle.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/sizzle/dist/sizzle.min.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/sizzle/dist/sizzle.min.map create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/traversing/var/dir.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/traversing/var/siblings.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/ObjectFunctionString.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/concat.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/document.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/documentElement.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/flat.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/fnToString.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/getProto.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/isFunction.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/isWindow.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/pop.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/rcheckableType.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/rcssNum.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/rnothtmlwhite.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/rnotwhite.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/rtrimCSS.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/sort.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/splice.js delete mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/strundefined.js create mode 100644 src/sampleWebAsWebApiClient/wwwroot/lib/jquery/src/var/whitespace.js diff --git a/.github/workflows/dotnet.yml b/.github/workflows/buildAndTest.yml similarity index 97% rename from .github/workflows/dotnet.yml rename to .github/workflows/buildAndTest.yml index c39ed77c..4be71514 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/buildAndTest.yml @@ -44,7 +44,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 9.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 0ef899a4..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,7 +0,0 @@ -on: workflow_call -jobs: - my_first_job: - runs-on: ubuntu-latest - steps: - - name: Run my action - uses: ./.github/worklflows/dotnet diff --git a/.gitignore b/.gitignore index c56cc0ea..19b51779 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ .paket/ .vs/ .sass-cache/ +.private/ /out bin diff --git a/.vscode/launch.json b/.vscode/launch.json index ed62f985..43c862cc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -43,7 +43,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceFolder}/src/Yavsc/bin/Debug/net8.0/Yavsc.dll", + "program": "${workspaceFolder}/src/Yavsc/bin/Debug/net9.0/Yavsc.dll", "args": [], "cwd": "${workspaceFolder}/src/Yavsc", "stopAtEntry": false, diff --git a/README.md b/README.md index 251ac1bc..ab9ae3a5 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,15 @@ C'est une application mettant en oeuvre une prise de contact entre un demandeur et, pour execution en environement de développement -``` - ~/workspace/yavsc/Yavsc @ ASPNETCORE_ENV=Development dotnet run +```bash +~/workspace/yavsc/Yavsc @ ASPNETCORE_ENV=Development dotnet run ``` ## Tests Utilisez GNU/Makefile (et visitez le code, dans le dossier `test` ): -[TOREDO] Depuis le répertoire racine: +[TODO] Depuis le répertoire racine: ```bash make test @@ -33,13 +33,14 @@ make test ## Installation / Déploiment / Développement -### les services kestrel et kestrel-pre - -[TODO] +### les services et l'API ### La Prod -Une fois sûr de vous, et une fois que Git dit propre votre copie de travail, depuis le répertoire `Yavsc`, lancez `make pushInProd`. +`cd srv/Yavsc` : `make pushInProd CONFIGURATION=Release`. + +puis, pour une première installation +`make install_service`. ## Fonctionalités (encore en cours de développement) diff --git a/contrib/yavsc.service b/contrib/yavsc.service new file mode 100644 index 00000000..21380320 --- /dev/null +++ b/contrib/yavsc.service @@ -0,0 +1,27 @@ +[Unit] +Description=Yavsc +After=syslog.target +After=network.target + +Wants=postgresql.service +After=postgresql.service + +[Service] +RestartSec=5s +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/srv/www/yavsc/ +ExecStart=/srv/www/yavsc/Yavsc +Restart=always +Environment="HOME=/srv/www/yavsc" +Environment="ASPNETCORE_ENVIRONMENT=Production" +Environment="ASPNETCORE_ConnectionStrings__DefaultConnection=YOUR Postgresql CONNECTION STRING" +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +AmbientCapabilities=CAP_NET_BIND_SERVICE +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=yavsc + +[Install] +WantedBy=multi-user.target diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index 6e024e9b..aa256182 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -1,12 +1,12 @@  - net8.0 + net9.0 enable enable 1c73094f-959f-4211-b1a1-6a69b236c283 - + diff --git a/src/Yavsc.Abstract/Google/Messaging/MessageWithPayLoad.cs b/src/Yavsc.Abstract/Google/Messaging/MessageWithPayLoad.cs index 62b61be4..ed683304 100644 --- a/src/Yavsc.Abstract/Google/Messaging/MessageWithPayLoad.cs +++ b/src/Yavsc.Abstract/Google/Messaging/MessageWithPayLoad.cs @@ -19,6 +19,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . +using Yavsc.Abstract.Models.Messaging; using Yavsc.Models.Messaging; namespace Yavsc.Models.Google.Messaging diff --git a/src/Yavsc.Abstract/Interfaces/IBaseTrackedEntity.cs b/src/Yavsc.Abstract/Interfaces/IBaseTrackedEntity.cs index f544f654..f87d9ef4 100644 --- a/src/Yavsc.Abstract/Interfaces/IBaseTrackedEntity.cs +++ b/src/Yavsc.Abstract/Interfaces/IBaseTrackedEntity.cs @@ -5,8 +5,8 @@ namespace Yavsc public interface ITrackedEntity { DateTime DateCreated { get; set; } - string UserCreated { get; set; } + string? UserCreated { get; set; } DateTime DateModified { get; set; } - string UserModified { get; set; } + string? UserModified { get; set; } } } diff --git a/src/Yavsc.Abstract/Messaging/Notification.cs b/src/Yavsc.Abstract/Messaging/Notification.cs index 2fbcb852..8b79e2c8 100644 --- a/src/Yavsc.Abstract/Messaging/Notification.cs +++ b/src/Yavsc.Abstract/Messaging/Notification.cs @@ -2,7 +2,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace Yavsc.Models.Messaging +namespace Yavsc.Abstract.Models.Messaging { /// /// A Notification, that mocks the one sent to Google, @@ -29,25 +29,25 @@ namespace Yavsc.Models.Messaging /// [StringLength(512)] [Display(Name = "Icône")] - public string icon { get; set; } + public string? icon { get; set; } /// /// The sound. /// [StringLength(512)] [Display(Name = "Son")] - public string sound { get; set; } + public string? sound { get; set; } /// /// The tag. /// [StringLength(512)] [Display(Name = "Tag")] - public string tag { get; set; } + public string? tag { get; set; } /// /// The color. /// [StringLength(512)] [Display(Name = "Couleur")] - public string color { get; set; } + public string? color { get; set; } /// /// The click action. /// @@ -63,7 +63,7 @@ namespace Yavsc.Models.Messaging /// /// [StringLength(512)] - public string Target { get; set; } + public string? Target { get; set; } public Notification() { diff --git a/src/Yavsc.Abstract/Yavsc.Abstract.csproj b/src/Yavsc.Abstract/Yavsc.Abstract.csproj index cc74758f..2ade24d2 100644 --- a/src/Yavsc.Abstract/Yavsc.Abstract.csproj +++ b/src/Yavsc.Abstract/Yavsc.Abstract.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 enable enable A shared model for a little client/server app, dealing about establishing some contract, between some human client and provider. diff --git a/src/Yavsc.Server/Migrations/20250613122253_notificationTarget.Designer.cs b/src/Yavsc.Server/Migrations/20250613122253_notificationTarget.Designer.cs new file mode 100644 index 00000000..31454f2a --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613122253_notificationTarget.Designer.cs @@ -0,0 +1,3509 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Yavsc.Models; + +#nullable disable + +namespace Yavsc.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250613122253_notificationTarget")] + partial class notificationTarget + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Yavsc.Abstract.Identity.ClientProviderInfo", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("text"); + + b.Property("BillingAddressId") + .HasColumnType("bigint"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("ClientProviderInfo"); + }); + + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.ToTable("Ban"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("UserId"); + + b.ToTable("BlackListed"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.Property("CircleId") + .HasColumnType("bigint"); + + b.Property("BlogPostId") + .HasColumnType("bigint"); + + b.HasKey("CircleId", "BlogPostId"); + + b.HasIndex("BlogPostId"); + + b.ToTable("CircleAuthorizationToBlogPost"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ContactCredits") + .HasColumnType("bigint"); + + b.Property("Credits") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.ToTable("BankStatus"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AllowMonthlyEmail") + .HasColumnType("boolean"); + + b.Property("Avatar") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("/images/Users/icon_user.png"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("DedicatedGoogleCalendar") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DiskQuota") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(524288000L); + + b.Property("DiskUsage") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxFileSize") + .HasColumnType("bigint"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PostalAddressId") + .HasColumnType("bigint"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasAlternateKey("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("PostalAddressId"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("AccessTokenLifetime") + .HasColumnType("integer"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogoutRedirectUri") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RedirectUri") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RefreshTokenLifeTime") + .HasColumnType("integer"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("Expiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresIn") + .IsRequired() + .HasColumnType("text"); + + b.Property("RefreshToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("OAuth2Tokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IssuedUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ProtectedTicket") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Scopes"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BalanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExecDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Impact") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BalanceId"); + + b.ToTable("BankBook"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BIC") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankedKey") + .HasColumnType("integer"); + + b.Property("IBAN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WicketCode") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("BankIdentity"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("EstimateId") + .HasColumnType("bigint"); + + b.Property("EstimateTemplateId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UnitaryCost") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("EstimateTemplateId"); + + b.ToTable("CommandLine"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AttachedFilesString") + .IsRequired() + .HasColumnType("text"); + + b.Property("AttachedGraphicsString") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CommandId") + .HasColumnType("bigint"); + + b.Property("CommandType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("CommandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Estimates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EstimateTemplates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.ExceptionSIREN", b => + { + b.Property("SIREN") + .HasColumnType("text"); + + b.HasKey("SIREN"); + + b.ToTable("ExceptionsSIREN"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(56224) + .HasColumnType("character varying(56224)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Photo") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("BlogSpot"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.Property("PostId") + .HasColumnType("bigint"); + + b.Property("TagId") + .HasColumnType("bigint"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlogTag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ParentId"); + + b.HasIndex("ReceiverId"); + + b.ToTable("Comment"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.HasKey("OwnerId"); + + b.ToTable("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Reccurence") + .HasColumnType("integer"); + + b.Property("ScheduleOwnerId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScheduleOwnerId"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("ScheduledEvent"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.Property("ConnectionId") + .HasColumnType("text"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Connected") + .HasColumnType("boolean"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ConnectionId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("ChatConnection"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestJoinPart") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name"); + + b.HasIndex("OwnerId"); + + b.ToTable("ChatRoom"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("ChannelName", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomAccess"); + }); + + modelBuilder.Entity("Yavsc.Models.Cratie.Option", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("CodeScrutin") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code", "CodeScrutin"); + + b.ToTable("Option"); + }); + + modelBuilder.Entity("Yavsc.Models.Drawing.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Blue") + .HasColumnType("smallint"); + + b.Property("Green") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Red") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Forms.Form", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Form"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ActionDistance") + .HasColumnType("integer"); + + b.Property("CarePrice") + .HasColumnType("numeric"); + + b.Property("FlatFeeDiscount") + .HasColumnType("numeric"); + + b.Property("HalfBalayagePrice") + .HasColumnType("numeric"); + + b.Property("HalfBrushingPrice") + .HasColumnType("numeric"); + + b.Property("HalfColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfDefrisPrice") + .HasColumnType("numeric"); + + b.Property("HalfFoldingPrice") + .HasColumnType("numeric"); + + b.Property("HalfMechPrice") + .HasColumnType("numeric"); + + b.Property("HalfMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfPermanentPrice") + .HasColumnType("numeric"); + + b.Property("KidCutPrice") + .HasColumnType("numeric"); + + b.Property("LongBalayagePrice") + .HasColumnType("numeric"); + + b.Property("LongBrushingPrice") + .HasColumnType("numeric"); + + b.Property("LongColorPrice") + .HasColumnType("numeric"); + + b.Property("LongDefrisPrice") + .HasColumnType("numeric"); + + b.Property("LongFoldingPrice") + .HasColumnType("numeric"); + + b.Property("LongMechPrice") + .HasColumnType("numeric"); + + b.Property("LongMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("LongPermanentPrice") + .HasColumnType("numeric"); + + b.Property("ManBrushPrice") + .HasColumnType("numeric"); + + b.Property("ManCutPrice") + .HasColumnType("numeric"); + + b.Property("ScheduleOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShampooPrice") + .HasColumnType("numeric"); + + b.Property("ShortBalayagePrice") + .HasColumnType("numeric"); + + b.Property("ShortBrushingPrice") + .HasColumnType("numeric"); + + b.Property("ShortColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortDefrisPrice") + .HasColumnType("numeric"); + + b.Property("ShortFoldingPrice") + .HasColumnType("numeric"); + + b.Property("ShortMechPrice") + .HasColumnType("numeric"); + + b.Property("ShortMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortPermanentPrice") + .HasColumnType("numeric"); + + b.Property("WomenHalfCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenLongCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenShortCutPrice") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.HasIndex("ScheduleOwnerId"); + + b.ToTable("BrusherProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("SelectedProfileUserId") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("PrestationId"); + + b.HasIndex("SelectedProfileUserId"); + + b.ToTable("HairCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("HairMultiCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Cares") + .HasColumnType("boolean"); + + b.Property("Cut") + .HasColumnType("boolean"); + + b.Property("Dressing") + .HasColumnType("integer"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("Length") + .HasColumnType("integer"); + + b.Property("Shampoo") + .HasColumnType("boolean"); + + b.Property("Tech") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("HairPrestation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("QueryId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PrestationId"); + + b.HasIndex("QueryId"); + + b.ToTable("HairPrestationCollectionItem"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Brand") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ColorId"); + + b.ToTable("HairTaint"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.Property("TaintId") + .HasColumnType("bigint"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.HasKey("TaintId", "PrestationId"); + + b.HasIndex("PrestationId"); + + b.ToTable("HairTaintInstance"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Evolution.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Feature"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FeatureId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("Bug"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeclarationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("LOCALTIMESTAMP"); + + b.Property("DeviceOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestActivityUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("Model") + .IsRequired() + .HasColumnType("text"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("DeviceId"); + + b.HasIndex("DeviceOwnerId"); + + b.ToTable("DeviceDeclaration"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Depth") + .HasColumnType("numeric"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.Property("Weight") + .HasColumnType("numeric"); + + b.Property("Width") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContextId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("For") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Sender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Announce"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.HasKey("UserId", "NotificationId"); + + b.HasIndex("NotificationId"); + + b.ToTable("DismissClicked"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Instrument"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasAlternateKey("InstrumentId", "OwnerId"); + + b.HasIndex("OwnerId"); + + b.ToTable("InstrumentRating"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.Property("OwnerProfileId") + .HasColumnType("text"); + + b.Property("DjSettingsUserId") + .HasColumnType("text"); + + b.Property("GeneralSettingsUserId") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("TendencyId") + .HasColumnType("bigint"); + + b.HasKey("OwnerProfileId"); + + b.HasIndex("DjSettingsUserId"); + + b.HasIndex("GeneralSettingsUserId"); + + b.ToTable("MusicalPreference"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalTendency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("MusicalTendency"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("SoundCloudId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("DjSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("GeneralSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("InstrumentId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("Instrumentation"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Property("CreationToken") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrderReference") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaypalPayerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("CreationToken"); + + b.HasIndex("ExecutorId"); + + b.ToTable("PayPalPayment"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Circle"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.Property("MemberId") + .HasColumnType("text"); + + b.Property("CircleId") + .HasColumnType("bigint"); + + b.HasKey("MemberId", "CircleId"); + + b.HasIndex("CircleId"); + + b.ToTable("CircleMembers"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("OwnerId", "UserId"); + + b.HasIndex("AddressId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.Property("HRef") + .HasColumnType("text"); + + b.Property("Method") + .HasColumnType("text"); + + b.Property("BrusherProfileUserId") + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("PayPalPaymentCreationToken") + .HasColumnType("text"); + + b.Property("Rel") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("HRef", "Method"); + + b.HasIndex("BrusherProfileUserId"); + + b.HasIndex("PayPalPaymentCreationToken"); + + b.ToTable("HyperLink"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.PostalAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Country") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street1") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street2") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SiteSkills"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DifferedFileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MediaType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Pitch") + .IsRequired() + .HasColumnType("text"); + + b.Property("SequenceNumber") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("LiveFlow"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hidden") + .HasColumnType("boolean"); + + b.Property("ModeratorGroupName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentCode") + .HasColumnType("text"); + + b.Property("Photo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SettingsClassName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code"); + + b.HasIndex("ParentCode"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FormationSettingsUserId") + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingForId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FormationSettingsUserId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("WorkingForId"); + + b.ToTable("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.ToTable("CommandForm"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Property("PerformerId") + .HasColumnType("text"); + + b.Property("AcceptNotifications") + .HasColumnType("boolean"); + + b.Property("AcceptPublicContact") + .HasColumnType("boolean"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("MaxDailyCost") + .HasColumnType("integer"); + + b.Property("MinDailyCost") + .HasColumnType("integer"); + + b.Property("OrganizationAddressId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SIREN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseGeoLocalizationToReduceDistanceWithClients") + .HasColumnType("boolean"); + + b.Property("WebSite") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PerformerId"); + + b.HasIndex("OrganizationAddressId"); + + b.ToTable("Performers"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("FormationSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("LocationType") + .HasColumnType("integer"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("RdvQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.Property("DoesCode") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Weight") + .HasColumnType("integer"); + + b.HasKey("DoesCode", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserActivities"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.Calendar.Period", b => + { + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Start", "End"); + + b.ToTable("Period"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.EMailing.MailingTemplate", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasMaxLength(65536) + .HasColumnType("character varying(65536)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyToAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToSend") + .HasColumnType("integer"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MailingTemplate"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GitId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("GitId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectBuildConfiguration"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Branch") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("GitRepositoryReference"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "TargetUser") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("BlackList") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Target") + .WithMany("ACL") + .HasForeignKey("BlogPostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Circle", "Allowed") + .WithMany() + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Allowed"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithOne("AccountBalance") + .HasForeignKey("Yavsc.Models.AccountBalance", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") + .WithMany() + .HasForeignKey("PostalAddressId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.HasOne("Yavsc.Models.AccountBalance", "Balance") + .WithMany() + .HasForeignKey("BalanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Balance"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("BankInfo") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.HasOne("Yavsc.Models.Billing.Estimate", null) + .WithMany("Bill") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Billing.EstimateTemplate", null) + .WithMany("Bill") + .HasForeignKey("EstimateTemplateId"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.RdvQuery", "Query") + .WithMany() + .HasForeignKey("CommandId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Owner"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany("Posts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Blog.Comment", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", null) + .WithMany("Events") + .HasForeignKey("ScheduleOwnerId"); + + b.HasOne("Yavsc.Server.Models.Calendar.Period", "Period") + .WithMany() + .HasForeignKey("PeriodStart", "PeriodEnd") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Period"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Connections") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Rooms") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.HasOne("Yavsc.Models.Chat.ChatRoom", "Room") + .WithMany("Moderation") + .HasForeignKey("ChannelName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("RoomAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Room"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BaseProfile"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", "SelectedProfile") + .WithMany() + .HasForeignKey("SelectedProfileUserId"); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Prestation"); + + b.Navigation("Regularisation"); + + b.Navigation("SelectedProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairMultiCutQuery", "Query") + .WithMany("Prestations") + .HasForeignKey("QueryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.HasOne("Yavsc.Models.Drawing.Color", "Color") + .WithMany() + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany("Taints") + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairTaint", "Taint") + .WithMany() + .HasForeignKey("TaintId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Taint"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.HasOne("Yavsc.Models.IT.Evolution.Feature", "False") + .WithMany() + .HasForeignKey("FeatureId"); + + b.Navigation("False"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "DeviceOwner") + .WithMany("DeviceDeclaration") + .HasForeignKey("DeviceOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceOwner"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Services") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notified"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Instrument") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Profile") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Instrument"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.HasOne("Yavsc.Models.Musical.Profiles.DjSettings", null) + .WithMany("SoundColor") + .HasForeignKey("DjSettingsUserId"); + + b.HasOne("Yavsc.Models.Musical.Profiles.GeneralSettings", null) + .WithMany("SoundColor") + .HasForeignKey("GeneralSettingsUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Tool") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tool"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Executor") + .WithMany() + .HasForeignKey("ExecutorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Executor"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Circles") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.HasOne("Yavsc.Models.Relationship.Circle", "Circle") + .WithMany("Members") + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Member") + .WithMany("Membership") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Circle"); + + b.Navigation("Member"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.HasOne("Yavsc.Models.Relationship.PostalAddress", "PostalAddress") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Book") + .HasForeignKey("ApplicationUserId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", null) + .WithMany("Links") + .HasForeignKey("BrusherProfileUserId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", null) + .WithMany("Links") + .HasForeignKey("PayPalPaymentCreationToken"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentCode"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.HasOne("Yavsc.Models.Workflow.Profiles.FormationSettings", null) + .WithMany("CoWorking") + .HasForeignKey("FormationSettingsUserId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "WorkingFor") + .WithMany() + .HasForeignKey("WorkingForId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Performer"); + + b.Navigation("WorkingFor"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Forms") + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "OrganizationAddress") + .WithMany() + .HasForeignKey("OrganizationAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationAddress"); + + b.Navigation("Performer"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Does") + .WithMany() + .HasForeignKey("DoesCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany("Activity") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Does"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", "Repository") + .WithMany() + .HasForeignKey("GitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + + b.Navigation("Repository"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.HasOne("Yavsc.Server.Models.IT.Project", "TargetProject") + .WithMany("Configurations") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetProject"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Navigation("AccountBalance") + .IsRequired(); + + b.Navigation("BankInfo"); + + b.Navigation("BlackList"); + + b.Navigation("Book"); + + b.Navigation("Circles"); + + b.Navigation("Connections"); + + b.Navigation("DeviceDeclaration"); + + b.Navigation("Membership"); + + b.Navigation("Posts"); + + b.Navigation("RoomAccess"); + + b.Navigation("Rooms"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Navigation("ACL"); + + b.Navigation("Comments"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Navigation("Moderation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Navigation("Prestations"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Navigation("Taints"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Navigation("Children"); + + b.Navigation("Forms"); + + b.Navigation("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Navigation("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Navigation("Configurations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613122253_notificationTarget.cs b/src/Yavsc.Server/Migrations/20250613122253_notificationTarget.cs new file mode 100644 index 00000000..4b858142 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613122253_notificationTarget.cs @@ -0,0 +1,51 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Yavsc.Migrations +{ + /// + public partial class notificationTarget : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Visible", + table: "BlogSpot"); + + migrationBuilder.AlterColumn( + name: "Target", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Target", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512, + oldNullable: true); + + migrationBuilder.AddColumn( + name: "Visible", + table: "BlogSpot", + type: "boolean", + nullable: false, + defaultValue: false); + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613123306_notificationNulls.Designer.cs b/src/Yavsc.Server/Migrations/20250613123306_notificationNulls.Designer.cs new file mode 100644 index 00000000..39e27f99 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613123306_notificationNulls.Designer.cs @@ -0,0 +1,3505 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Yavsc.Models; + +#nullable disable + +namespace Yavsc.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250613123306_notificationNulls")] + partial class notificationNulls + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Yavsc.Abstract.Identity.ClientProviderInfo", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("text"); + + b.Property("BillingAddressId") + .HasColumnType("bigint"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("ClientProviderInfo"); + }); + + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.ToTable("Ban"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("UserId"); + + b.ToTable("BlackListed"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.Property("CircleId") + .HasColumnType("bigint"); + + b.Property("BlogPostId") + .HasColumnType("bigint"); + + b.HasKey("CircleId", "BlogPostId"); + + b.HasIndex("BlogPostId"); + + b.ToTable("CircleAuthorizationToBlogPost"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ContactCredits") + .HasColumnType("bigint"); + + b.Property("Credits") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.ToTable("BankStatus"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AllowMonthlyEmail") + .HasColumnType("boolean"); + + b.Property("Avatar") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("/images/Users/icon_user.png"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("DedicatedGoogleCalendar") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DiskQuota") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(524288000L); + + b.Property("DiskUsage") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxFileSize") + .HasColumnType("bigint"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PostalAddressId") + .HasColumnType("bigint"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasAlternateKey("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("PostalAddressId"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("AccessTokenLifetime") + .HasColumnType("integer"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogoutRedirectUri") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RedirectUri") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RefreshTokenLifeTime") + .HasColumnType("integer"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("Expiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresIn") + .IsRequired() + .HasColumnType("text"); + + b.Property("RefreshToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("OAuth2Tokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IssuedUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ProtectedTicket") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Scopes"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BalanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExecDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Impact") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BalanceId"); + + b.ToTable("BankBook"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BIC") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankedKey") + .HasColumnType("integer"); + + b.Property("IBAN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WicketCode") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("BankIdentity"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("EstimateId") + .HasColumnType("bigint"); + + b.Property("EstimateTemplateId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UnitaryCost") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("EstimateTemplateId"); + + b.ToTable("CommandLine"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AttachedFilesString") + .IsRequired() + .HasColumnType("text"); + + b.Property("AttachedGraphicsString") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CommandId") + .HasColumnType("bigint"); + + b.Property("CommandType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("CommandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Estimates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EstimateTemplates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.ExceptionSIREN", b => + { + b.Property("SIREN") + .HasColumnType("text"); + + b.HasKey("SIREN"); + + b.ToTable("ExceptionsSIREN"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(56224) + .HasColumnType("character varying(56224)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Photo") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("BlogSpot"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.Property("PostId") + .HasColumnType("bigint"); + + b.Property("TagId") + .HasColumnType("bigint"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlogTag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ParentId"); + + b.HasIndex("ReceiverId"); + + b.ToTable("Comment"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.HasKey("OwnerId"); + + b.ToTable("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Reccurence") + .HasColumnType("integer"); + + b.Property("ScheduleOwnerId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScheduleOwnerId"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("ScheduledEvent"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.Property("ConnectionId") + .HasColumnType("text"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Connected") + .HasColumnType("boolean"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ConnectionId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("ChatConnection"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestJoinPart") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name"); + + b.HasIndex("OwnerId"); + + b.ToTable("ChatRoom"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("ChannelName", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomAccess"); + }); + + modelBuilder.Entity("Yavsc.Models.Cratie.Option", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("CodeScrutin") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code", "CodeScrutin"); + + b.ToTable("Option"); + }); + + modelBuilder.Entity("Yavsc.Models.Drawing.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Blue") + .HasColumnType("smallint"); + + b.Property("Green") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Red") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Forms.Form", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Form"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ActionDistance") + .HasColumnType("integer"); + + b.Property("CarePrice") + .HasColumnType("numeric"); + + b.Property("FlatFeeDiscount") + .HasColumnType("numeric"); + + b.Property("HalfBalayagePrice") + .HasColumnType("numeric"); + + b.Property("HalfBrushingPrice") + .HasColumnType("numeric"); + + b.Property("HalfColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfDefrisPrice") + .HasColumnType("numeric"); + + b.Property("HalfFoldingPrice") + .HasColumnType("numeric"); + + b.Property("HalfMechPrice") + .HasColumnType("numeric"); + + b.Property("HalfMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfPermanentPrice") + .HasColumnType("numeric"); + + b.Property("KidCutPrice") + .HasColumnType("numeric"); + + b.Property("LongBalayagePrice") + .HasColumnType("numeric"); + + b.Property("LongBrushingPrice") + .HasColumnType("numeric"); + + b.Property("LongColorPrice") + .HasColumnType("numeric"); + + b.Property("LongDefrisPrice") + .HasColumnType("numeric"); + + b.Property("LongFoldingPrice") + .HasColumnType("numeric"); + + b.Property("LongMechPrice") + .HasColumnType("numeric"); + + b.Property("LongMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("LongPermanentPrice") + .HasColumnType("numeric"); + + b.Property("ManBrushPrice") + .HasColumnType("numeric"); + + b.Property("ManCutPrice") + .HasColumnType("numeric"); + + b.Property("ScheduleOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShampooPrice") + .HasColumnType("numeric"); + + b.Property("ShortBalayagePrice") + .HasColumnType("numeric"); + + b.Property("ShortBrushingPrice") + .HasColumnType("numeric"); + + b.Property("ShortColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortDefrisPrice") + .HasColumnType("numeric"); + + b.Property("ShortFoldingPrice") + .HasColumnType("numeric"); + + b.Property("ShortMechPrice") + .HasColumnType("numeric"); + + b.Property("ShortMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortPermanentPrice") + .HasColumnType("numeric"); + + b.Property("WomenHalfCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenLongCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenShortCutPrice") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.HasIndex("ScheduleOwnerId"); + + b.ToTable("BrusherProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("SelectedProfileUserId") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("PrestationId"); + + b.HasIndex("SelectedProfileUserId"); + + b.ToTable("HairCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("HairMultiCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Cares") + .HasColumnType("boolean"); + + b.Property("Cut") + .HasColumnType("boolean"); + + b.Property("Dressing") + .HasColumnType("integer"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("Length") + .HasColumnType("integer"); + + b.Property("Shampoo") + .HasColumnType("boolean"); + + b.Property("Tech") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("HairPrestation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("QueryId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PrestationId"); + + b.HasIndex("QueryId"); + + b.ToTable("HairPrestationCollectionItem"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Brand") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ColorId"); + + b.ToTable("HairTaint"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.Property("TaintId") + .HasColumnType("bigint"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.HasKey("TaintId", "PrestationId"); + + b.HasIndex("PrestationId"); + + b.ToTable("HairTaintInstance"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Evolution.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Feature"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FeatureId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("Bug"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeclarationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("LOCALTIMESTAMP"); + + b.Property("DeviceOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestActivityUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("Model") + .IsRequired() + .HasColumnType("text"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("DeviceId"); + + b.HasIndex("DeviceOwnerId"); + + b.ToTable("DeviceDeclaration"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Depth") + .HasColumnType("numeric"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.Property("Weight") + .HasColumnType("numeric"); + + b.Property("Width") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContextId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("For") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Sender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Announce"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.HasKey("UserId", "NotificationId"); + + b.HasIndex("NotificationId"); + + b.ToTable("DismissClicked"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Instrument"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasAlternateKey("InstrumentId", "OwnerId"); + + b.HasIndex("OwnerId"); + + b.ToTable("InstrumentRating"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.Property("OwnerProfileId") + .HasColumnType("text"); + + b.Property("DjSettingsUserId") + .HasColumnType("text"); + + b.Property("GeneralSettingsUserId") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("TendencyId") + .HasColumnType("bigint"); + + b.HasKey("OwnerProfileId"); + + b.HasIndex("DjSettingsUserId"); + + b.HasIndex("GeneralSettingsUserId"); + + b.ToTable("MusicalPreference"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalTendency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("MusicalTendency"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("SoundCloudId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("DjSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("GeneralSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("InstrumentId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("Instrumentation"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Property("CreationToken") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrderReference") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaypalPayerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("CreationToken"); + + b.HasIndex("ExecutorId"); + + b.ToTable("PayPalPayment"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Circle"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.Property("MemberId") + .HasColumnType("text"); + + b.Property("CircleId") + .HasColumnType("bigint"); + + b.HasKey("MemberId", "CircleId"); + + b.HasIndex("CircleId"); + + b.ToTable("CircleMembers"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("OwnerId", "UserId"); + + b.HasIndex("AddressId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.Property("HRef") + .HasColumnType("text"); + + b.Property("Method") + .HasColumnType("text"); + + b.Property("BrusherProfileUserId") + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("PayPalPaymentCreationToken") + .HasColumnType("text"); + + b.Property("Rel") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("HRef", "Method"); + + b.HasIndex("BrusherProfileUserId"); + + b.HasIndex("PayPalPaymentCreationToken"); + + b.ToTable("HyperLink"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.PostalAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Country") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street1") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street2") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SiteSkills"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DifferedFileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MediaType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Pitch") + .IsRequired() + .HasColumnType("text"); + + b.Property("SequenceNumber") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("LiveFlow"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hidden") + .HasColumnType("boolean"); + + b.Property("ModeratorGroupName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentCode") + .HasColumnType("text"); + + b.Property("Photo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SettingsClassName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code"); + + b.HasIndex("ParentCode"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FormationSettingsUserId") + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingForId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FormationSettingsUserId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("WorkingForId"); + + b.ToTable("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.ToTable("CommandForm"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Property("PerformerId") + .HasColumnType("text"); + + b.Property("AcceptNotifications") + .HasColumnType("boolean"); + + b.Property("AcceptPublicContact") + .HasColumnType("boolean"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("MaxDailyCost") + .HasColumnType("integer"); + + b.Property("MinDailyCost") + .HasColumnType("integer"); + + b.Property("OrganizationAddressId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SIREN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseGeoLocalizationToReduceDistanceWithClients") + .HasColumnType("boolean"); + + b.Property("WebSite") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PerformerId"); + + b.HasIndex("OrganizationAddressId"); + + b.ToTable("Performers"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("FormationSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("LocationType") + .HasColumnType("integer"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("RdvQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.Property("DoesCode") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Weight") + .HasColumnType("integer"); + + b.HasKey("DoesCode", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserActivities"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.Calendar.Period", b => + { + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Start", "End"); + + b.ToTable("Period"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.EMailing.MailingTemplate", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasMaxLength(65536) + .HasColumnType("character varying(65536)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyToAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToSend") + .HasColumnType("integer"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MailingTemplate"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GitId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("GitId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectBuildConfiguration"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Branch") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("GitRepositoryReference"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "TargetUser") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("BlackList") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Target") + .WithMany("ACL") + .HasForeignKey("BlogPostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Circle", "Allowed") + .WithMany() + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Allowed"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithOne("AccountBalance") + .HasForeignKey("Yavsc.Models.AccountBalance", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") + .WithMany() + .HasForeignKey("PostalAddressId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.HasOne("Yavsc.Models.AccountBalance", "Balance") + .WithMany() + .HasForeignKey("BalanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Balance"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("BankInfo") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.HasOne("Yavsc.Models.Billing.Estimate", null) + .WithMany("Bill") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Billing.EstimateTemplate", null) + .WithMany("Bill") + .HasForeignKey("EstimateTemplateId"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.RdvQuery", "Query") + .WithMany() + .HasForeignKey("CommandId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Owner"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany("Posts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Blog.Comment", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", null) + .WithMany("Events") + .HasForeignKey("ScheduleOwnerId"); + + b.HasOne("Yavsc.Server.Models.Calendar.Period", "Period") + .WithMany() + .HasForeignKey("PeriodStart", "PeriodEnd") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Period"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Connections") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Rooms") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.HasOne("Yavsc.Models.Chat.ChatRoom", "Room") + .WithMany("Moderation") + .HasForeignKey("ChannelName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("RoomAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Room"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BaseProfile"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", "SelectedProfile") + .WithMany() + .HasForeignKey("SelectedProfileUserId"); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Prestation"); + + b.Navigation("Regularisation"); + + b.Navigation("SelectedProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairMultiCutQuery", "Query") + .WithMany("Prestations") + .HasForeignKey("QueryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.HasOne("Yavsc.Models.Drawing.Color", "Color") + .WithMany() + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany("Taints") + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairTaint", "Taint") + .WithMany() + .HasForeignKey("TaintId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Taint"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.HasOne("Yavsc.Models.IT.Evolution.Feature", "False") + .WithMany() + .HasForeignKey("FeatureId"); + + b.Navigation("False"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "DeviceOwner") + .WithMany("DeviceDeclaration") + .HasForeignKey("DeviceOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceOwner"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Services") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notified"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Instrument") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Profile") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Instrument"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.HasOne("Yavsc.Models.Musical.Profiles.DjSettings", null) + .WithMany("SoundColor") + .HasForeignKey("DjSettingsUserId"); + + b.HasOne("Yavsc.Models.Musical.Profiles.GeneralSettings", null) + .WithMany("SoundColor") + .HasForeignKey("GeneralSettingsUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Tool") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tool"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Executor") + .WithMany() + .HasForeignKey("ExecutorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Executor"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Circles") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.HasOne("Yavsc.Models.Relationship.Circle", "Circle") + .WithMany("Members") + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Member") + .WithMany("Membership") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Circle"); + + b.Navigation("Member"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.HasOne("Yavsc.Models.Relationship.PostalAddress", "PostalAddress") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Book") + .HasForeignKey("ApplicationUserId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", null) + .WithMany("Links") + .HasForeignKey("BrusherProfileUserId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", null) + .WithMany("Links") + .HasForeignKey("PayPalPaymentCreationToken"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentCode"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.HasOne("Yavsc.Models.Workflow.Profiles.FormationSettings", null) + .WithMany("CoWorking") + .HasForeignKey("FormationSettingsUserId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "WorkingFor") + .WithMany() + .HasForeignKey("WorkingForId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Performer"); + + b.Navigation("WorkingFor"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Forms") + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "OrganizationAddress") + .WithMany() + .HasForeignKey("OrganizationAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationAddress"); + + b.Navigation("Performer"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Does") + .WithMany() + .HasForeignKey("DoesCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany("Activity") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Does"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", "Repository") + .WithMany() + .HasForeignKey("GitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + + b.Navigation("Repository"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.HasOne("Yavsc.Server.Models.IT.Project", "TargetProject") + .WithMany("Configurations") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetProject"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Navigation("AccountBalance") + .IsRequired(); + + b.Navigation("BankInfo"); + + b.Navigation("BlackList"); + + b.Navigation("Book"); + + b.Navigation("Circles"); + + b.Navigation("Connections"); + + b.Navigation("DeviceDeclaration"); + + b.Navigation("Membership"); + + b.Navigation("Posts"); + + b.Navigation("RoomAccess"); + + b.Navigation("Rooms"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Navigation("ACL"); + + b.Navigation("Comments"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Navigation("Moderation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Navigation("Prestations"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Navigation("Taints"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Navigation("Children"); + + b.Navigation("Forms"); + + b.Navigation("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Navigation("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Navigation("Configurations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613123306_notificationNulls.cs b/src/Yavsc.Server/Migrations/20250613123306_notificationNulls.cs new file mode 100644 index 00000000..794dfae2 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613123306_notificationNulls.cs @@ -0,0 +1,109 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Yavsc.Migrations +{ + /// + public partial class notificationNulls : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "tag", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512); + + migrationBuilder.AlterColumn( + name: "sound", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512); + + migrationBuilder.AlterColumn( + name: "icon", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: true, + defaultValue: "exclam", + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512, + oldDefaultValue: "exclam"); + + migrationBuilder.AlterColumn( + name: "color", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "tag", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "sound", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "icon", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: false, + defaultValue: "exclam", + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512, + oldNullable: true, + oldDefaultValue: "exclam"); + + migrationBuilder.AlterColumn( + name: "color", + table: "Notification", + type: "character varying(512)", + maxLength: 512, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(512)", + oldMaxLength: 512, + oldNullable: true); + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613131533_trackedNulls.Designer.cs b/src/Yavsc.Server/Migrations/20250613131533_trackedNulls.Designer.cs new file mode 100644 index 00000000..61b92b47 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613131533_trackedNulls.Designer.cs @@ -0,0 +1,3505 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Yavsc.Models; + +#nullable disable + +namespace Yavsc.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250613131533_trackedNulls")] + partial class trackedNulls + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Yavsc.Abstract.Identity.ClientProviderInfo", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("text"); + + b.Property("BillingAddressId") + .HasColumnType("bigint"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("ClientProviderInfo"); + }); + + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.ToTable("Ban"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("UserId"); + + b.ToTable("BlackListed"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.Property("CircleId") + .HasColumnType("bigint"); + + b.Property("BlogPostId") + .HasColumnType("bigint"); + + b.HasKey("CircleId", "BlogPostId"); + + b.HasIndex("BlogPostId"); + + b.ToTable("CircleAuthorizationToBlogPost"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ContactCredits") + .HasColumnType("bigint"); + + b.Property("Credits") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.ToTable("BankStatus"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AllowMonthlyEmail") + .HasColumnType("boolean"); + + b.Property("Avatar") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("/images/Users/icon_user.png"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("DedicatedGoogleCalendar") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DiskQuota") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(524288000L); + + b.Property("DiskUsage") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxFileSize") + .HasColumnType("bigint"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PostalAddressId") + .HasColumnType("bigint"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasAlternateKey("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("PostalAddressId"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("AccessTokenLifetime") + .HasColumnType("integer"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogoutRedirectUri") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RedirectUri") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RefreshTokenLifeTime") + .HasColumnType("integer"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("Expiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresIn") + .IsRequired() + .HasColumnType("text"); + + b.Property("RefreshToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("OAuth2Tokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IssuedUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ProtectedTicket") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Scopes"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BalanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExecDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Impact") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BalanceId"); + + b.ToTable("BankBook"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BIC") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankedKey") + .HasColumnType("integer"); + + b.Property("IBAN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WicketCode") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("BankIdentity"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("EstimateId") + .HasColumnType("bigint"); + + b.Property("EstimateTemplateId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UnitaryCost") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("EstimateTemplateId"); + + b.ToTable("CommandLine"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AttachedFilesString") + .IsRequired() + .HasColumnType("text"); + + b.Property("AttachedGraphicsString") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CommandId") + .HasColumnType("bigint"); + + b.Property("CommandType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("CommandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Estimates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EstimateTemplates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.ExceptionSIREN", b => + { + b.Property("SIREN") + .HasColumnType("text"); + + b.HasKey("SIREN"); + + b.ToTable("ExceptionsSIREN"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(56224) + .HasColumnType("character varying(56224)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Photo") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("BlogSpot"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.Property("PostId") + .HasColumnType("bigint"); + + b.Property("TagId") + .HasColumnType("bigint"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlogTag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ParentId"); + + b.HasIndex("ReceiverId"); + + b.ToTable("Comment"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.HasKey("OwnerId"); + + b.ToTable("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Reccurence") + .HasColumnType("integer"); + + b.Property("ScheduleOwnerId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScheduleOwnerId"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("ScheduledEvent"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.Property("ConnectionId") + .HasColumnType("text"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Connected") + .HasColumnType("boolean"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ConnectionId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("ChatConnection"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestJoinPart") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name"); + + b.HasIndex("OwnerId"); + + b.ToTable("ChatRoom"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("ChannelName", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomAccess"); + }); + + modelBuilder.Entity("Yavsc.Models.Cratie.Option", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("CodeScrutin") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code", "CodeScrutin"); + + b.ToTable("Option"); + }); + + modelBuilder.Entity("Yavsc.Models.Drawing.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Blue") + .HasColumnType("smallint"); + + b.Property("Green") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Red") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Forms.Form", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Form"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ActionDistance") + .HasColumnType("integer"); + + b.Property("CarePrice") + .HasColumnType("numeric"); + + b.Property("FlatFeeDiscount") + .HasColumnType("numeric"); + + b.Property("HalfBalayagePrice") + .HasColumnType("numeric"); + + b.Property("HalfBrushingPrice") + .HasColumnType("numeric"); + + b.Property("HalfColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfDefrisPrice") + .HasColumnType("numeric"); + + b.Property("HalfFoldingPrice") + .HasColumnType("numeric"); + + b.Property("HalfMechPrice") + .HasColumnType("numeric"); + + b.Property("HalfMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfPermanentPrice") + .HasColumnType("numeric"); + + b.Property("KidCutPrice") + .HasColumnType("numeric"); + + b.Property("LongBalayagePrice") + .HasColumnType("numeric"); + + b.Property("LongBrushingPrice") + .HasColumnType("numeric"); + + b.Property("LongColorPrice") + .HasColumnType("numeric"); + + b.Property("LongDefrisPrice") + .HasColumnType("numeric"); + + b.Property("LongFoldingPrice") + .HasColumnType("numeric"); + + b.Property("LongMechPrice") + .HasColumnType("numeric"); + + b.Property("LongMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("LongPermanentPrice") + .HasColumnType("numeric"); + + b.Property("ManBrushPrice") + .HasColumnType("numeric"); + + b.Property("ManCutPrice") + .HasColumnType("numeric"); + + b.Property("ScheduleOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShampooPrice") + .HasColumnType("numeric"); + + b.Property("ShortBalayagePrice") + .HasColumnType("numeric"); + + b.Property("ShortBrushingPrice") + .HasColumnType("numeric"); + + b.Property("ShortColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortDefrisPrice") + .HasColumnType("numeric"); + + b.Property("ShortFoldingPrice") + .HasColumnType("numeric"); + + b.Property("ShortMechPrice") + .HasColumnType("numeric"); + + b.Property("ShortMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortPermanentPrice") + .HasColumnType("numeric"); + + b.Property("WomenHalfCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenLongCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenShortCutPrice") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.HasIndex("ScheduleOwnerId"); + + b.ToTable("BrusherProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("SelectedProfileUserId") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("PrestationId"); + + b.HasIndex("SelectedProfileUserId"); + + b.ToTable("HairCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("HairMultiCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Cares") + .HasColumnType("boolean"); + + b.Property("Cut") + .HasColumnType("boolean"); + + b.Property("Dressing") + .HasColumnType("integer"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("Length") + .HasColumnType("integer"); + + b.Property("Shampoo") + .HasColumnType("boolean"); + + b.Property("Tech") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("HairPrestation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("QueryId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PrestationId"); + + b.HasIndex("QueryId"); + + b.ToTable("HairPrestationCollectionItem"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Brand") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ColorId"); + + b.ToTable("HairTaint"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.Property("TaintId") + .HasColumnType("bigint"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.HasKey("TaintId", "PrestationId"); + + b.HasIndex("PrestationId"); + + b.ToTable("HairTaintInstance"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Evolution.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Feature"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FeatureId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("Bug"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeclarationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("LOCALTIMESTAMP"); + + b.Property("DeviceOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestActivityUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("Model") + .IsRequired() + .HasColumnType("text"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("DeviceId"); + + b.HasIndex("DeviceOwnerId"); + + b.ToTable("DeviceDeclaration"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Depth") + .HasColumnType("numeric"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.Property("Weight") + .HasColumnType("numeric"); + + b.Property("Width") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContextId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("For") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Sender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Announce"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.HasKey("UserId", "NotificationId"); + + b.HasIndex("NotificationId"); + + b.ToTable("DismissClicked"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Instrument"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasAlternateKey("InstrumentId", "OwnerId"); + + b.HasIndex("OwnerId"); + + b.ToTable("InstrumentRating"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.Property("OwnerProfileId") + .HasColumnType("text"); + + b.Property("DjSettingsUserId") + .HasColumnType("text"); + + b.Property("GeneralSettingsUserId") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("TendencyId") + .HasColumnType("bigint"); + + b.HasKey("OwnerProfileId"); + + b.HasIndex("DjSettingsUserId"); + + b.HasIndex("GeneralSettingsUserId"); + + b.ToTable("MusicalPreference"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalTendency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("MusicalTendency"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("SoundCloudId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("DjSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("GeneralSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("InstrumentId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("Instrumentation"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Property("CreationToken") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrderReference") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaypalPayerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("CreationToken"); + + b.HasIndex("ExecutorId"); + + b.ToTable("PayPalPayment"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Circle"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.Property("MemberId") + .HasColumnType("text"); + + b.Property("CircleId") + .HasColumnType("bigint"); + + b.HasKey("MemberId", "CircleId"); + + b.HasIndex("CircleId"); + + b.ToTable("CircleMembers"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("OwnerId", "UserId"); + + b.HasIndex("AddressId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.Property("HRef") + .HasColumnType("text"); + + b.Property("Method") + .HasColumnType("text"); + + b.Property("BrusherProfileUserId") + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("PayPalPaymentCreationToken") + .HasColumnType("text"); + + b.Property("Rel") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("HRef", "Method"); + + b.HasIndex("BrusherProfileUserId"); + + b.HasIndex("PayPalPaymentCreationToken"); + + b.ToTable("HyperLink"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.PostalAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Country") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street1") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street2") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SiteSkills"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DifferedFileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MediaType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Pitch") + .IsRequired() + .HasColumnType("text"); + + b.Property("SequenceNumber") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("LiveFlow"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hidden") + .HasColumnType("boolean"); + + b.Property("ModeratorGroupName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentCode") + .HasColumnType("text"); + + b.Property("Photo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SettingsClassName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code"); + + b.HasIndex("ParentCode"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FormationSettingsUserId") + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingForId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FormationSettingsUserId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("WorkingForId"); + + b.ToTable("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.ToTable("CommandForm"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Property("PerformerId") + .HasColumnType("text"); + + b.Property("AcceptNotifications") + .HasColumnType("boolean"); + + b.Property("AcceptPublicContact") + .HasColumnType("boolean"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("MaxDailyCost") + .HasColumnType("integer"); + + b.Property("MinDailyCost") + .HasColumnType("integer"); + + b.Property("OrganizationAddressId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SIREN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseGeoLocalizationToReduceDistanceWithClients") + .HasColumnType("boolean"); + + b.Property("WebSite") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PerformerId"); + + b.HasIndex("OrganizationAddressId"); + + b.ToTable("Performers"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("FormationSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("LocationType") + .HasColumnType("integer"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("RdvQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.Property("DoesCode") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Weight") + .HasColumnType("integer"); + + b.HasKey("DoesCode", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserActivities"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.Calendar.Period", b => + { + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Start", "End"); + + b.ToTable("Period"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.EMailing.MailingTemplate", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasMaxLength(65536) + .HasColumnType("character varying(65536)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyToAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToSend") + .HasColumnType("integer"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MailingTemplate"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GitId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("GitId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectBuildConfiguration"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Branch") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("GitRepositoryReference"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "TargetUser") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("BlackList") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Target") + .WithMany("ACL") + .HasForeignKey("BlogPostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Circle", "Allowed") + .WithMany() + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Allowed"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithOne("AccountBalance") + .HasForeignKey("Yavsc.Models.AccountBalance", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") + .WithMany() + .HasForeignKey("PostalAddressId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.HasOne("Yavsc.Models.AccountBalance", "Balance") + .WithMany() + .HasForeignKey("BalanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Balance"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("BankInfo") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.HasOne("Yavsc.Models.Billing.Estimate", null) + .WithMany("Bill") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Billing.EstimateTemplate", null) + .WithMany("Bill") + .HasForeignKey("EstimateTemplateId"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.RdvQuery", "Query") + .WithMany() + .HasForeignKey("CommandId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Owner"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany("Posts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Blog.Comment", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", null) + .WithMany("Events") + .HasForeignKey("ScheduleOwnerId"); + + b.HasOne("Yavsc.Server.Models.Calendar.Period", "Period") + .WithMany() + .HasForeignKey("PeriodStart", "PeriodEnd") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Period"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Connections") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Rooms") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.HasOne("Yavsc.Models.Chat.ChatRoom", "Room") + .WithMany("Moderation") + .HasForeignKey("ChannelName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("RoomAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Room"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BaseProfile"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", "SelectedProfile") + .WithMany() + .HasForeignKey("SelectedProfileUserId"); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Prestation"); + + b.Navigation("Regularisation"); + + b.Navigation("SelectedProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairMultiCutQuery", "Query") + .WithMany("Prestations") + .HasForeignKey("QueryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.HasOne("Yavsc.Models.Drawing.Color", "Color") + .WithMany() + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany("Taints") + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairTaint", "Taint") + .WithMany() + .HasForeignKey("TaintId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Taint"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.HasOne("Yavsc.Models.IT.Evolution.Feature", "False") + .WithMany() + .HasForeignKey("FeatureId"); + + b.Navigation("False"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "DeviceOwner") + .WithMany("DeviceDeclaration") + .HasForeignKey("DeviceOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceOwner"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Services") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notified"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Instrument") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Profile") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Instrument"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.HasOne("Yavsc.Models.Musical.Profiles.DjSettings", null) + .WithMany("SoundColor") + .HasForeignKey("DjSettingsUserId"); + + b.HasOne("Yavsc.Models.Musical.Profiles.GeneralSettings", null) + .WithMany("SoundColor") + .HasForeignKey("GeneralSettingsUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Tool") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tool"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Executor") + .WithMany() + .HasForeignKey("ExecutorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Executor"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Circles") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.HasOne("Yavsc.Models.Relationship.Circle", "Circle") + .WithMany("Members") + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Member") + .WithMany("Membership") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Circle"); + + b.Navigation("Member"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.HasOne("Yavsc.Models.Relationship.PostalAddress", "PostalAddress") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Book") + .HasForeignKey("ApplicationUserId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", null) + .WithMany("Links") + .HasForeignKey("BrusherProfileUserId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", null) + .WithMany("Links") + .HasForeignKey("PayPalPaymentCreationToken"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentCode"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.HasOne("Yavsc.Models.Workflow.Profiles.FormationSettings", null) + .WithMany("CoWorking") + .HasForeignKey("FormationSettingsUserId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "WorkingFor") + .WithMany() + .HasForeignKey("WorkingForId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Performer"); + + b.Navigation("WorkingFor"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Forms") + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "OrganizationAddress") + .WithMany() + .HasForeignKey("OrganizationAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationAddress"); + + b.Navigation("Performer"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Does") + .WithMany() + .HasForeignKey("DoesCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany("Activity") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Does"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", "Repository") + .WithMany() + .HasForeignKey("GitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + + b.Navigation("Repository"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.HasOne("Yavsc.Server.Models.IT.Project", "TargetProject") + .WithMany("Configurations") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetProject"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Navigation("AccountBalance") + .IsRequired(); + + b.Navigation("BankInfo"); + + b.Navigation("BlackList"); + + b.Navigation("Book"); + + b.Navigation("Circles"); + + b.Navigation("Connections"); + + b.Navigation("DeviceDeclaration"); + + b.Navigation("Membership"); + + b.Navigation("Posts"); + + b.Navigation("RoomAccess"); + + b.Navigation("Rooms"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Navigation("ACL"); + + b.Navigation("Comments"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Navigation("Moderation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Navigation("Prestations"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Navigation("Taints"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Navigation("Children"); + + b.Navigation("Forms"); + + b.Navigation("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Navigation("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Navigation("Configurations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613131533_trackedNulls.cs b/src/Yavsc.Server/Migrations/20250613131533_trackedNulls.cs new file mode 100644 index 00000000..724f7d0a --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613131533_trackedNulls.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Yavsc.Migrations +{ + /// + public partial class trackedNulls : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613131836_blogNulls.Designer.cs b/src/Yavsc.Server/Migrations/20250613131836_blogNulls.Designer.cs new file mode 100644 index 00000000..4f905adc --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613131836_blogNulls.Designer.cs @@ -0,0 +1,3503 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Yavsc.Models; + +#nullable disable + +namespace Yavsc.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250613131836_blogNulls")] + partial class blogNulls + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Yavsc.Abstract.Identity.ClientProviderInfo", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("text"); + + b.Property("BillingAddressId") + .HasColumnType("bigint"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("ClientProviderInfo"); + }); + + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.ToTable("Ban"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("UserId"); + + b.ToTable("BlackListed"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.Property("CircleId") + .HasColumnType("bigint"); + + b.Property("BlogPostId") + .HasColumnType("bigint"); + + b.HasKey("CircleId", "BlogPostId"); + + b.HasIndex("BlogPostId"); + + b.ToTable("CircleAuthorizationToBlogPost"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ContactCredits") + .HasColumnType("bigint"); + + b.Property("Credits") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.ToTable("BankStatus"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AllowMonthlyEmail") + .HasColumnType("boolean"); + + b.Property("Avatar") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("/images/Users/icon_user.png"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("DedicatedGoogleCalendar") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DiskQuota") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(524288000L); + + b.Property("DiskUsage") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxFileSize") + .HasColumnType("bigint"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PostalAddressId") + .HasColumnType("bigint"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasAlternateKey("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("PostalAddressId"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("AccessTokenLifetime") + .HasColumnType("integer"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogoutRedirectUri") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RedirectUri") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RefreshTokenLifeTime") + .HasColumnType("integer"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("Expiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresIn") + .IsRequired() + .HasColumnType("text"); + + b.Property("RefreshToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("OAuth2Tokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IssuedUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ProtectedTicket") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Scopes"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BalanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExecDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Impact") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BalanceId"); + + b.ToTable("BankBook"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BIC") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankedKey") + .HasColumnType("integer"); + + b.Property("IBAN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WicketCode") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("BankIdentity"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("EstimateId") + .HasColumnType("bigint"); + + b.Property("EstimateTemplateId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UnitaryCost") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("EstimateTemplateId"); + + b.ToTable("CommandLine"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AttachedFilesString") + .IsRequired() + .HasColumnType("text"); + + b.Property("AttachedGraphicsString") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CommandId") + .HasColumnType("bigint"); + + b.Property("CommandType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("CommandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Estimates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EstimateTemplates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.ExceptionSIREN", b => + { + b.Property("SIREN") + .HasColumnType("text"); + + b.HasKey("SIREN"); + + b.ToTable("ExceptionsSIREN"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(56224) + .HasColumnType("character varying(56224)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Photo") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserCreated") + .HasColumnType("text"); + + b.Property("UserModified") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("BlogSpot"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.Property("PostId") + .HasColumnType("bigint"); + + b.Property("TagId") + .HasColumnType("bigint"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlogTag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ParentId"); + + b.HasIndex("ReceiverId"); + + b.ToTable("Comment"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.HasKey("OwnerId"); + + b.ToTable("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Reccurence") + .HasColumnType("integer"); + + b.Property("ScheduleOwnerId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScheduleOwnerId"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("ScheduledEvent"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.Property("ConnectionId") + .HasColumnType("text"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Connected") + .HasColumnType("boolean"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ConnectionId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("ChatConnection"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestJoinPart") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name"); + + b.HasIndex("OwnerId"); + + b.ToTable("ChatRoom"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("ChannelName", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomAccess"); + }); + + modelBuilder.Entity("Yavsc.Models.Cratie.Option", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("CodeScrutin") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code", "CodeScrutin"); + + b.ToTable("Option"); + }); + + modelBuilder.Entity("Yavsc.Models.Drawing.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Blue") + .HasColumnType("smallint"); + + b.Property("Green") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Red") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Forms.Form", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Form"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ActionDistance") + .HasColumnType("integer"); + + b.Property("CarePrice") + .HasColumnType("numeric"); + + b.Property("FlatFeeDiscount") + .HasColumnType("numeric"); + + b.Property("HalfBalayagePrice") + .HasColumnType("numeric"); + + b.Property("HalfBrushingPrice") + .HasColumnType("numeric"); + + b.Property("HalfColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfDefrisPrice") + .HasColumnType("numeric"); + + b.Property("HalfFoldingPrice") + .HasColumnType("numeric"); + + b.Property("HalfMechPrice") + .HasColumnType("numeric"); + + b.Property("HalfMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfPermanentPrice") + .HasColumnType("numeric"); + + b.Property("KidCutPrice") + .HasColumnType("numeric"); + + b.Property("LongBalayagePrice") + .HasColumnType("numeric"); + + b.Property("LongBrushingPrice") + .HasColumnType("numeric"); + + b.Property("LongColorPrice") + .HasColumnType("numeric"); + + b.Property("LongDefrisPrice") + .HasColumnType("numeric"); + + b.Property("LongFoldingPrice") + .HasColumnType("numeric"); + + b.Property("LongMechPrice") + .HasColumnType("numeric"); + + b.Property("LongMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("LongPermanentPrice") + .HasColumnType("numeric"); + + b.Property("ManBrushPrice") + .HasColumnType("numeric"); + + b.Property("ManCutPrice") + .HasColumnType("numeric"); + + b.Property("ScheduleOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShampooPrice") + .HasColumnType("numeric"); + + b.Property("ShortBalayagePrice") + .HasColumnType("numeric"); + + b.Property("ShortBrushingPrice") + .HasColumnType("numeric"); + + b.Property("ShortColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortDefrisPrice") + .HasColumnType("numeric"); + + b.Property("ShortFoldingPrice") + .HasColumnType("numeric"); + + b.Property("ShortMechPrice") + .HasColumnType("numeric"); + + b.Property("ShortMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortPermanentPrice") + .HasColumnType("numeric"); + + b.Property("WomenHalfCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenLongCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenShortCutPrice") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.HasIndex("ScheduleOwnerId"); + + b.ToTable("BrusherProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("SelectedProfileUserId") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("PrestationId"); + + b.HasIndex("SelectedProfileUserId"); + + b.ToTable("HairCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("HairMultiCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Cares") + .HasColumnType("boolean"); + + b.Property("Cut") + .HasColumnType("boolean"); + + b.Property("Dressing") + .HasColumnType("integer"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("Length") + .HasColumnType("integer"); + + b.Property("Shampoo") + .HasColumnType("boolean"); + + b.Property("Tech") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("HairPrestation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("QueryId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PrestationId"); + + b.HasIndex("QueryId"); + + b.ToTable("HairPrestationCollectionItem"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Brand") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ColorId"); + + b.ToTable("HairTaint"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.Property("TaintId") + .HasColumnType("bigint"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.HasKey("TaintId", "PrestationId"); + + b.HasIndex("PrestationId"); + + b.ToTable("HairTaintInstance"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Evolution.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Feature"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FeatureId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("Bug"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeclarationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("LOCALTIMESTAMP"); + + b.Property("DeviceOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestActivityUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("Model") + .IsRequired() + .HasColumnType("text"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("DeviceId"); + + b.HasIndex("DeviceOwnerId"); + + b.ToTable("DeviceDeclaration"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Depth") + .HasColumnType("numeric"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.Property("Weight") + .HasColumnType("numeric"); + + b.Property("Width") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContextId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("For") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Sender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Announce"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.HasKey("UserId", "NotificationId"); + + b.HasIndex("NotificationId"); + + b.ToTable("DismissClicked"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Instrument"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasAlternateKey("InstrumentId", "OwnerId"); + + b.HasIndex("OwnerId"); + + b.ToTable("InstrumentRating"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.Property("OwnerProfileId") + .HasColumnType("text"); + + b.Property("DjSettingsUserId") + .HasColumnType("text"); + + b.Property("GeneralSettingsUserId") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("TendencyId") + .HasColumnType("bigint"); + + b.HasKey("OwnerProfileId"); + + b.HasIndex("DjSettingsUserId"); + + b.HasIndex("GeneralSettingsUserId"); + + b.ToTable("MusicalPreference"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalTendency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("MusicalTendency"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("SoundCloudId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("DjSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("GeneralSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("InstrumentId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("Instrumentation"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Property("CreationToken") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrderReference") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaypalPayerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("CreationToken"); + + b.HasIndex("ExecutorId"); + + b.ToTable("PayPalPayment"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Circle"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.Property("MemberId") + .HasColumnType("text"); + + b.Property("CircleId") + .HasColumnType("bigint"); + + b.HasKey("MemberId", "CircleId"); + + b.HasIndex("CircleId"); + + b.ToTable("CircleMembers"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("OwnerId", "UserId"); + + b.HasIndex("AddressId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.Property("HRef") + .HasColumnType("text"); + + b.Property("Method") + .HasColumnType("text"); + + b.Property("BrusherProfileUserId") + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("PayPalPaymentCreationToken") + .HasColumnType("text"); + + b.Property("Rel") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("HRef", "Method"); + + b.HasIndex("BrusherProfileUserId"); + + b.HasIndex("PayPalPaymentCreationToken"); + + b.ToTable("HyperLink"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.PostalAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Country") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street1") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street2") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SiteSkills"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DifferedFileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MediaType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Pitch") + .IsRequired() + .HasColumnType("text"); + + b.Property("SequenceNumber") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("LiveFlow"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hidden") + .HasColumnType("boolean"); + + b.Property("ModeratorGroupName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentCode") + .HasColumnType("text"); + + b.Property("Photo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SettingsClassName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code"); + + b.HasIndex("ParentCode"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FormationSettingsUserId") + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingForId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FormationSettingsUserId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("WorkingForId"); + + b.ToTable("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.ToTable("CommandForm"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Property("PerformerId") + .HasColumnType("text"); + + b.Property("AcceptNotifications") + .HasColumnType("boolean"); + + b.Property("AcceptPublicContact") + .HasColumnType("boolean"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("MaxDailyCost") + .HasColumnType("integer"); + + b.Property("MinDailyCost") + .HasColumnType("integer"); + + b.Property("OrganizationAddressId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SIREN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseGeoLocalizationToReduceDistanceWithClients") + .HasColumnType("boolean"); + + b.Property("WebSite") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PerformerId"); + + b.HasIndex("OrganizationAddressId"); + + b.ToTable("Performers"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("FormationSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("LocationType") + .HasColumnType("integer"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("RdvQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.Property("DoesCode") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Weight") + .HasColumnType("integer"); + + b.HasKey("DoesCode", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserActivities"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.Calendar.Period", b => + { + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Start", "End"); + + b.ToTable("Period"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.EMailing.MailingTemplate", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasMaxLength(65536) + .HasColumnType("character varying(65536)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyToAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToSend") + .HasColumnType("integer"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MailingTemplate"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GitId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("GitId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectBuildConfiguration"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Branch") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("GitRepositoryReference"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "TargetUser") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("BlackList") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Target") + .WithMany("ACL") + .HasForeignKey("BlogPostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Circle", "Allowed") + .WithMany() + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Allowed"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithOne("AccountBalance") + .HasForeignKey("Yavsc.Models.AccountBalance", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") + .WithMany() + .HasForeignKey("PostalAddressId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.HasOne("Yavsc.Models.AccountBalance", "Balance") + .WithMany() + .HasForeignKey("BalanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Balance"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("BankInfo") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.HasOne("Yavsc.Models.Billing.Estimate", null) + .WithMany("Bill") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Billing.EstimateTemplate", null) + .WithMany("Bill") + .HasForeignKey("EstimateTemplateId"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.RdvQuery", "Query") + .WithMany() + .HasForeignKey("CommandId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Owner"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany("Posts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Blog.Comment", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", null) + .WithMany("Events") + .HasForeignKey("ScheduleOwnerId"); + + b.HasOne("Yavsc.Server.Models.Calendar.Period", "Period") + .WithMany() + .HasForeignKey("PeriodStart", "PeriodEnd") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Period"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Connections") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Rooms") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.HasOne("Yavsc.Models.Chat.ChatRoom", "Room") + .WithMany("Moderation") + .HasForeignKey("ChannelName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("RoomAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Room"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BaseProfile"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", "SelectedProfile") + .WithMany() + .HasForeignKey("SelectedProfileUserId"); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Prestation"); + + b.Navigation("Regularisation"); + + b.Navigation("SelectedProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairMultiCutQuery", "Query") + .WithMany("Prestations") + .HasForeignKey("QueryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.HasOne("Yavsc.Models.Drawing.Color", "Color") + .WithMany() + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany("Taints") + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairTaint", "Taint") + .WithMany() + .HasForeignKey("TaintId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Taint"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.HasOne("Yavsc.Models.IT.Evolution.Feature", "False") + .WithMany() + .HasForeignKey("FeatureId"); + + b.Navigation("False"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "DeviceOwner") + .WithMany("DeviceDeclaration") + .HasForeignKey("DeviceOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceOwner"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Services") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notified"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Instrument") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Profile") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Instrument"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.HasOne("Yavsc.Models.Musical.Profiles.DjSettings", null) + .WithMany("SoundColor") + .HasForeignKey("DjSettingsUserId"); + + b.HasOne("Yavsc.Models.Musical.Profiles.GeneralSettings", null) + .WithMany("SoundColor") + .HasForeignKey("GeneralSettingsUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Tool") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tool"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Executor") + .WithMany() + .HasForeignKey("ExecutorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Executor"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Circles") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.HasOne("Yavsc.Models.Relationship.Circle", "Circle") + .WithMany("Members") + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Member") + .WithMany("Membership") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Circle"); + + b.Navigation("Member"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.HasOne("Yavsc.Models.Relationship.PostalAddress", "PostalAddress") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Book") + .HasForeignKey("ApplicationUserId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", null) + .WithMany("Links") + .HasForeignKey("BrusherProfileUserId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", null) + .WithMany("Links") + .HasForeignKey("PayPalPaymentCreationToken"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentCode"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.HasOne("Yavsc.Models.Workflow.Profiles.FormationSettings", null) + .WithMany("CoWorking") + .HasForeignKey("FormationSettingsUserId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "WorkingFor") + .WithMany() + .HasForeignKey("WorkingForId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Performer"); + + b.Navigation("WorkingFor"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Forms") + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "OrganizationAddress") + .WithMany() + .HasForeignKey("OrganizationAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationAddress"); + + b.Navigation("Performer"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Does") + .WithMany() + .HasForeignKey("DoesCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany("Activity") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Does"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", "Repository") + .WithMany() + .HasForeignKey("GitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + + b.Navigation("Repository"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.HasOne("Yavsc.Server.Models.IT.Project", "TargetProject") + .WithMany("Configurations") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetProject"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Navigation("AccountBalance") + .IsRequired(); + + b.Navigation("BankInfo"); + + b.Navigation("BlackList"); + + b.Navigation("Book"); + + b.Navigation("Circles"); + + b.Navigation("Connections"); + + b.Navigation("DeviceDeclaration"); + + b.Navigation("Membership"); + + b.Navigation("Posts"); + + b.Navigation("RoomAccess"); + + b.Navigation("Rooms"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Navigation("ACL"); + + b.Navigation("Comments"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Navigation("Moderation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Navigation("Prestations"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Navigation("Taints"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Navigation("Children"); + + b.Navigation("Forms"); + + b.Navigation("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Navigation("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Navigation("Configurations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613131836_blogNulls.cs b/src/Yavsc.Server/Migrations/20250613131836_blogNulls.cs new file mode 100644 index 00000000..22df9178 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613131836_blogNulls.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Yavsc.Migrations +{ + /// + public partial class blogNulls : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UserModified", + table: "BlogSpot", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "UserCreated", + table: "BlogSpot", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UserModified", + table: "BlogSpot", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserCreated", + table: "BlogSpot", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.Designer.cs b/src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.Designer.cs new file mode 100644 index 00000000..75da28c4 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.Designer.cs @@ -0,0 +1,3502 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Yavsc.Models; + +#nullable disable + +namespace Yavsc.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250613132139_BlogPostInputViewModelNulls")] + partial class BlogPostInputViewModelNulls + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Yavsc.Abstract.Identity.ClientProviderInfo", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("text"); + + b.Property("BillingAddressId") + .HasColumnType("bigint"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("ClientProviderInfo"); + }); + + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.ToTable("Ban"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("UserId"); + + b.ToTable("BlackListed"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.Property("CircleId") + .HasColumnType("bigint"); + + b.Property("BlogPostId") + .HasColumnType("bigint"); + + b.HasKey("CircleId", "BlogPostId"); + + b.HasIndex("BlogPostId"); + + b.ToTable("CircleAuthorizationToBlogPost"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ContactCredits") + .HasColumnType("bigint"); + + b.Property("Credits") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.ToTable("BankStatus"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AllowMonthlyEmail") + .HasColumnType("boolean"); + + b.Property("Avatar") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("/images/Users/icon_user.png"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("DedicatedGoogleCalendar") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DiskQuota") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(524288000L); + + b.Property("DiskUsage") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxFileSize") + .HasColumnType("bigint"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PostalAddressId") + .HasColumnType("bigint"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasAlternateKey("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("PostalAddressId"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("AccessTokenLifetime") + .HasColumnType("integer"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogoutRedirectUri") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RedirectUri") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RefreshTokenLifeTime") + .HasColumnType("integer"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("Expiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresIn") + .IsRequired() + .HasColumnType("text"); + + b.Property("RefreshToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("OAuth2Tokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IssuedUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ProtectedTicket") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Scopes"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BalanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExecDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Impact") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BalanceId"); + + b.ToTable("BankBook"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BIC") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankedKey") + .HasColumnType("integer"); + + b.Property("IBAN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WicketCode") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("BankIdentity"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("EstimateId") + .HasColumnType("bigint"); + + b.Property("EstimateTemplateId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UnitaryCost") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("EstimateTemplateId"); + + b.ToTable("CommandLine"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AttachedFilesString") + .IsRequired() + .HasColumnType("text"); + + b.Property("AttachedGraphicsString") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CommandId") + .HasColumnType("bigint"); + + b.Property("CommandType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("CommandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Estimates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EstimateTemplates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.ExceptionSIREN", b => + { + b.Property("SIREN") + .HasColumnType("text"); + + b.HasKey("SIREN"); + + b.ToTable("ExceptionsSIREN"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .HasMaxLength(56224) + .HasColumnType("character varying(56224)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Photo") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserCreated") + .HasColumnType("text"); + + b.Property("UserModified") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("BlogSpot"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.Property("PostId") + .HasColumnType("bigint"); + + b.Property("TagId") + .HasColumnType("bigint"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlogTag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ParentId"); + + b.HasIndex("ReceiverId"); + + b.ToTable("Comment"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.HasKey("OwnerId"); + + b.ToTable("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Reccurence") + .HasColumnType("integer"); + + b.Property("ScheduleOwnerId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScheduleOwnerId"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("ScheduledEvent"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.Property("ConnectionId") + .HasColumnType("text"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Connected") + .HasColumnType("boolean"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ConnectionId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("ChatConnection"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestJoinPart") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name"); + + b.HasIndex("OwnerId"); + + b.ToTable("ChatRoom"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("ChannelName", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomAccess"); + }); + + modelBuilder.Entity("Yavsc.Models.Cratie.Option", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("CodeScrutin") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code", "CodeScrutin"); + + b.ToTable("Option"); + }); + + modelBuilder.Entity("Yavsc.Models.Drawing.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Blue") + .HasColumnType("smallint"); + + b.Property("Green") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Red") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Forms.Form", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Form"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ActionDistance") + .HasColumnType("integer"); + + b.Property("CarePrice") + .HasColumnType("numeric"); + + b.Property("FlatFeeDiscount") + .HasColumnType("numeric"); + + b.Property("HalfBalayagePrice") + .HasColumnType("numeric"); + + b.Property("HalfBrushingPrice") + .HasColumnType("numeric"); + + b.Property("HalfColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfDefrisPrice") + .HasColumnType("numeric"); + + b.Property("HalfFoldingPrice") + .HasColumnType("numeric"); + + b.Property("HalfMechPrice") + .HasColumnType("numeric"); + + b.Property("HalfMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfPermanentPrice") + .HasColumnType("numeric"); + + b.Property("KidCutPrice") + .HasColumnType("numeric"); + + b.Property("LongBalayagePrice") + .HasColumnType("numeric"); + + b.Property("LongBrushingPrice") + .HasColumnType("numeric"); + + b.Property("LongColorPrice") + .HasColumnType("numeric"); + + b.Property("LongDefrisPrice") + .HasColumnType("numeric"); + + b.Property("LongFoldingPrice") + .HasColumnType("numeric"); + + b.Property("LongMechPrice") + .HasColumnType("numeric"); + + b.Property("LongMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("LongPermanentPrice") + .HasColumnType("numeric"); + + b.Property("ManBrushPrice") + .HasColumnType("numeric"); + + b.Property("ManCutPrice") + .HasColumnType("numeric"); + + b.Property("ScheduleOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShampooPrice") + .HasColumnType("numeric"); + + b.Property("ShortBalayagePrice") + .HasColumnType("numeric"); + + b.Property("ShortBrushingPrice") + .HasColumnType("numeric"); + + b.Property("ShortColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortDefrisPrice") + .HasColumnType("numeric"); + + b.Property("ShortFoldingPrice") + .HasColumnType("numeric"); + + b.Property("ShortMechPrice") + .HasColumnType("numeric"); + + b.Property("ShortMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortPermanentPrice") + .HasColumnType("numeric"); + + b.Property("WomenHalfCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenLongCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenShortCutPrice") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.HasIndex("ScheduleOwnerId"); + + b.ToTable("BrusherProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("SelectedProfileUserId") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("PrestationId"); + + b.HasIndex("SelectedProfileUserId"); + + b.ToTable("HairCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("HairMultiCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Cares") + .HasColumnType("boolean"); + + b.Property("Cut") + .HasColumnType("boolean"); + + b.Property("Dressing") + .HasColumnType("integer"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("Length") + .HasColumnType("integer"); + + b.Property("Shampoo") + .HasColumnType("boolean"); + + b.Property("Tech") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("HairPrestation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("QueryId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PrestationId"); + + b.HasIndex("QueryId"); + + b.ToTable("HairPrestationCollectionItem"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Brand") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ColorId"); + + b.ToTable("HairTaint"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.Property("TaintId") + .HasColumnType("bigint"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.HasKey("TaintId", "PrestationId"); + + b.HasIndex("PrestationId"); + + b.ToTable("HairTaintInstance"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Evolution.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Feature"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FeatureId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("Bug"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeclarationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("LOCALTIMESTAMP"); + + b.Property("DeviceOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestActivityUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("Model") + .IsRequired() + .HasColumnType("text"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("DeviceId"); + + b.HasIndex("DeviceOwnerId"); + + b.ToTable("DeviceDeclaration"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Depth") + .HasColumnType("numeric"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.Property("Weight") + .HasColumnType("numeric"); + + b.Property("Width") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContextId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("For") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Sender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Announce"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.HasKey("UserId", "NotificationId"); + + b.HasIndex("NotificationId"); + + b.ToTable("DismissClicked"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Instrument"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasAlternateKey("InstrumentId", "OwnerId"); + + b.HasIndex("OwnerId"); + + b.ToTable("InstrumentRating"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.Property("OwnerProfileId") + .HasColumnType("text"); + + b.Property("DjSettingsUserId") + .HasColumnType("text"); + + b.Property("GeneralSettingsUserId") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("TendencyId") + .HasColumnType("bigint"); + + b.HasKey("OwnerProfileId"); + + b.HasIndex("DjSettingsUserId"); + + b.HasIndex("GeneralSettingsUserId"); + + b.ToTable("MusicalPreference"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalTendency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("MusicalTendency"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("SoundCloudId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("DjSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("GeneralSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("InstrumentId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("Instrumentation"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Property("CreationToken") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrderReference") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaypalPayerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("CreationToken"); + + b.HasIndex("ExecutorId"); + + b.ToTable("PayPalPayment"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Circle"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.Property("MemberId") + .HasColumnType("text"); + + b.Property("CircleId") + .HasColumnType("bigint"); + + b.HasKey("MemberId", "CircleId"); + + b.HasIndex("CircleId"); + + b.ToTable("CircleMembers"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("OwnerId", "UserId"); + + b.HasIndex("AddressId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.Property("HRef") + .HasColumnType("text"); + + b.Property("Method") + .HasColumnType("text"); + + b.Property("BrusherProfileUserId") + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("PayPalPaymentCreationToken") + .HasColumnType("text"); + + b.Property("Rel") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("HRef", "Method"); + + b.HasIndex("BrusherProfileUserId"); + + b.HasIndex("PayPalPaymentCreationToken"); + + b.ToTable("HyperLink"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.PostalAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Country") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street1") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street2") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SiteSkills"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DifferedFileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MediaType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Pitch") + .IsRequired() + .HasColumnType("text"); + + b.Property("SequenceNumber") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("LiveFlow"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hidden") + .HasColumnType("boolean"); + + b.Property("ModeratorGroupName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentCode") + .HasColumnType("text"); + + b.Property("Photo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SettingsClassName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code"); + + b.HasIndex("ParentCode"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FormationSettingsUserId") + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingForId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FormationSettingsUserId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("WorkingForId"); + + b.ToTable("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.ToTable("CommandForm"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Property("PerformerId") + .HasColumnType("text"); + + b.Property("AcceptNotifications") + .HasColumnType("boolean"); + + b.Property("AcceptPublicContact") + .HasColumnType("boolean"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("MaxDailyCost") + .HasColumnType("integer"); + + b.Property("MinDailyCost") + .HasColumnType("integer"); + + b.Property("OrganizationAddressId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SIREN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseGeoLocalizationToReduceDistanceWithClients") + .HasColumnType("boolean"); + + b.Property("WebSite") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PerformerId"); + + b.HasIndex("OrganizationAddressId"); + + b.ToTable("Performers"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("FormationSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("LocationType") + .HasColumnType("integer"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("RdvQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.Property("DoesCode") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Weight") + .HasColumnType("integer"); + + b.HasKey("DoesCode", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserActivities"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.Calendar.Period", b => + { + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Start", "End"); + + b.ToTable("Period"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.EMailing.MailingTemplate", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasMaxLength(65536) + .HasColumnType("character varying(65536)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyToAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToSend") + .HasColumnType("integer"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MailingTemplate"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GitId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("GitId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectBuildConfiguration"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Branch") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("GitRepositoryReference"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "TargetUser") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("BlackList") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Target") + .WithMany("ACL") + .HasForeignKey("BlogPostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Circle", "Allowed") + .WithMany() + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Allowed"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithOne("AccountBalance") + .HasForeignKey("Yavsc.Models.AccountBalance", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") + .WithMany() + .HasForeignKey("PostalAddressId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.HasOne("Yavsc.Models.AccountBalance", "Balance") + .WithMany() + .HasForeignKey("BalanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Balance"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("BankInfo") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.HasOne("Yavsc.Models.Billing.Estimate", null) + .WithMany("Bill") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Billing.EstimateTemplate", null) + .WithMany("Bill") + .HasForeignKey("EstimateTemplateId"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.RdvQuery", "Query") + .WithMany() + .HasForeignKey("CommandId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Owner"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany("Posts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Blog.Comment", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", null) + .WithMany("Events") + .HasForeignKey("ScheduleOwnerId"); + + b.HasOne("Yavsc.Server.Models.Calendar.Period", "Period") + .WithMany() + .HasForeignKey("PeriodStart", "PeriodEnd") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Period"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Connections") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Rooms") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.HasOne("Yavsc.Models.Chat.ChatRoom", "Room") + .WithMany("Moderation") + .HasForeignKey("ChannelName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("RoomAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Room"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BaseProfile"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", "SelectedProfile") + .WithMany() + .HasForeignKey("SelectedProfileUserId"); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Prestation"); + + b.Navigation("Regularisation"); + + b.Navigation("SelectedProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairMultiCutQuery", "Query") + .WithMany("Prestations") + .HasForeignKey("QueryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.HasOne("Yavsc.Models.Drawing.Color", "Color") + .WithMany() + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany("Taints") + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairTaint", "Taint") + .WithMany() + .HasForeignKey("TaintId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Taint"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.HasOne("Yavsc.Models.IT.Evolution.Feature", "False") + .WithMany() + .HasForeignKey("FeatureId"); + + b.Navigation("False"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "DeviceOwner") + .WithMany("DeviceDeclaration") + .HasForeignKey("DeviceOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceOwner"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Services") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notified"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Instrument") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Profile") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Instrument"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.HasOne("Yavsc.Models.Musical.Profiles.DjSettings", null) + .WithMany("SoundColor") + .HasForeignKey("DjSettingsUserId"); + + b.HasOne("Yavsc.Models.Musical.Profiles.GeneralSettings", null) + .WithMany("SoundColor") + .HasForeignKey("GeneralSettingsUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Tool") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tool"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Executor") + .WithMany() + .HasForeignKey("ExecutorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Executor"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Circles") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.HasOne("Yavsc.Models.Relationship.Circle", "Circle") + .WithMany("Members") + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Member") + .WithMany("Membership") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Circle"); + + b.Navigation("Member"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.HasOne("Yavsc.Models.Relationship.PostalAddress", "PostalAddress") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Book") + .HasForeignKey("ApplicationUserId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", null) + .WithMany("Links") + .HasForeignKey("BrusherProfileUserId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", null) + .WithMany("Links") + .HasForeignKey("PayPalPaymentCreationToken"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentCode"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.HasOne("Yavsc.Models.Workflow.Profiles.FormationSettings", null) + .WithMany("CoWorking") + .HasForeignKey("FormationSettingsUserId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "WorkingFor") + .WithMany() + .HasForeignKey("WorkingForId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Performer"); + + b.Navigation("WorkingFor"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Forms") + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "OrganizationAddress") + .WithMany() + .HasForeignKey("OrganizationAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationAddress"); + + b.Navigation("Performer"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Does") + .WithMany() + .HasForeignKey("DoesCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany("Activity") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Does"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", "Repository") + .WithMany() + .HasForeignKey("GitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + + b.Navigation("Repository"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.HasOne("Yavsc.Server.Models.IT.Project", "TargetProject") + .WithMany("Configurations") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetProject"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Navigation("AccountBalance") + .IsRequired(); + + b.Navigation("BankInfo"); + + b.Navigation("BlackList"); + + b.Navigation("Book"); + + b.Navigation("Circles"); + + b.Navigation("Connections"); + + b.Navigation("DeviceDeclaration"); + + b.Navigation("Membership"); + + b.Navigation("Posts"); + + b.Navigation("RoomAccess"); + + b.Navigation("Rooms"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Navigation("ACL"); + + b.Navigation("Comments"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Navigation("Moderation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Navigation("Prestations"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Navigation("Taints"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Navigation("Children"); + + b.Navigation("Forms"); + + b.Navigation("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Navigation("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Navigation("Configurations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.cs b/src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.cs new file mode 100644 index 00000000..737e5e72 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613132139_BlogPostInputViewModelNulls.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Yavsc.Migrations +{ + /// + public partial class BlogPostInputViewModelNulls : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Content", + table: "BlogSpot", + type: "character varying(56224)", + maxLength: 56224, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(56224)", + oldMaxLength: 56224); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Content", + table: "BlogSpot", + type: "character varying(56224)", + maxLength: 56224, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(56224)", + oldMaxLength: 56224, + oldNullable: true); + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.Designer.cs b/src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.Designer.cs new file mode 100644 index 00000000..810489e1 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.Designer.cs @@ -0,0 +1,3497 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Yavsc.Models; + +#nullable disable + +namespace Yavsc.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250613181510_ActivityNulls")] + partial class ActivityNulls + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Yavsc.Abstract.Identity.ClientProviderInfo", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("text"); + + b.Property("BillingAddressId") + .HasColumnType("bigint"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("ClientProviderInfo"); + }); + + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.ToTable("Ban"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("UserId"); + + b.ToTable("BlackListed"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.Property("CircleId") + .HasColumnType("bigint"); + + b.Property("BlogPostId") + .HasColumnType("bigint"); + + b.HasKey("CircleId", "BlogPostId"); + + b.HasIndex("BlogPostId"); + + b.ToTable("CircleAuthorizationToBlogPost"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ContactCredits") + .HasColumnType("bigint"); + + b.Property("Credits") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.ToTable("BankStatus"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AllowMonthlyEmail") + .HasColumnType("boolean"); + + b.Property("Avatar") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("/images/Users/icon_user.png"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("DedicatedGoogleCalendar") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DiskQuota") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(524288000L); + + b.Property("DiskUsage") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxFileSize") + .HasColumnType("bigint"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PostalAddressId") + .HasColumnType("bigint"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasAlternateKey("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("PostalAddressId"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("AccessTokenLifetime") + .HasColumnType("integer"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogoutRedirectUri") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RedirectUri") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RefreshTokenLifeTime") + .HasColumnType("integer"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("Expiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresIn") + .IsRequired() + .HasColumnType("text"); + + b.Property("RefreshToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("OAuth2Tokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IssuedUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ProtectedTicket") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Yavsc.Models.Auth.Scope", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Scopes"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BalanceId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExecDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Impact") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BalanceId"); + + b.ToTable("BankBook"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("BIC") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("BankedKey") + .HasColumnType("integer"); + + b.Property("IBAN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WicketCode") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("BankIdentity"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("EstimateId") + .HasColumnType("bigint"); + + b.Property("EstimateTemplateId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UnitaryCost") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("EstimateTemplateId"); + + b.ToTable("CommandLine"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AttachedFilesString") + .IsRequired() + .HasColumnType("text"); + + b.Property("AttachedGraphicsString") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CommandId") + .HasColumnType("bigint"); + + b.Property("CommandType") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("CommandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Estimates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EstimateTemplates"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.ExceptionSIREN", b => + { + b.Property("SIREN") + .HasColumnType("text"); + + b.HasKey("SIREN"); + + b.ToTable("ExceptionsSIREN"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .HasMaxLength(56224) + .HasColumnType("character varying(56224)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Photo") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserCreated") + .HasColumnType("text"); + + b.Property("UserModified") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("BlogSpot"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.Property("PostId") + .HasColumnType("bigint"); + + b.Property("TagId") + .HasColumnType("bigint"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlogTag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ParentId"); + + b.HasIndex("ReceiverId"); + + b.ToTable("Comment"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.HasKey("OwnerId"); + + b.ToTable("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Reccurence") + .HasColumnType("integer"); + + b.Property("ScheduleOwnerId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScheduleOwnerId"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("ScheduledEvent"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.Property("ConnectionId") + .HasColumnType("text"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Connected") + .HasColumnType("boolean"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ConnectionId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("ChatConnection"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestJoinPart") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name"); + + b.HasIndex("OwnerId"); + + b.ToTable("ChatRoom"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("ChannelName", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomAccess"); + }); + + modelBuilder.Entity("Yavsc.Models.Cratie.Option", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("CodeScrutin") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Code", "CodeScrutin"); + + b.ToTable("Option"); + }); + + modelBuilder.Entity("Yavsc.Models.Drawing.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Blue") + .HasColumnType("smallint"); + + b.Property("Green") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Red") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Forms.Form", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Form"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("ActionDistance") + .HasColumnType("integer"); + + b.Property("CarePrice") + .HasColumnType("numeric"); + + b.Property("FlatFeeDiscount") + .HasColumnType("numeric"); + + b.Property("HalfBalayagePrice") + .HasColumnType("numeric"); + + b.Property("HalfBrushingPrice") + .HasColumnType("numeric"); + + b.Property("HalfColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfDefrisPrice") + .HasColumnType("numeric"); + + b.Property("HalfFoldingPrice") + .HasColumnType("numeric"); + + b.Property("HalfMechPrice") + .HasColumnType("numeric"); + + b.Property("HalfMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("HalfPermanentPrice") + .HasColumnType("numeric"); + + b.Property("KidCutPrice") + .HasColumnType("numeric"); + + b.Property("LongBalayagePrice") + .HasColumnType("numeric"); + + b.Property("LongBrushingPrice") + .HasColumnType("numeric"); + + b.Property("LongColorPrice") + .HasColumnType("numeric"); + + b.Property("LongDefrisPrice") + .HasColumnType("numeric"); + + b.Property("LongFoldingPrice") + .HasColumnType("numeric"); + + b.Property("LongMechPrice") + .HasColumnType("numeric"); + + b.Property("LongMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("LongPermanentPrice") + .HasColumnType("numeric"); + + b.Property("ManBrushPrice") + .HasColumnType("numeric"); + + b.Property("ManCutPrice") + .HasColumnType("numeric"); + + b.Property("ScheduleOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShampooPrice") + .HasColumnType("numeric"); + + b.Property("ShortBalayagePrice") + .HasColumnType("numeric"); + + b.Property("ShortBrushingPrice") + .HasColumnType("numeric"); + + b.Property("ShortColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortDefrisPrice") + .HasColumnType("numeric"); + + b.Property("ShortFoldingPrice") + .HasColumnType("numeric"); + + b.Property("ShortMechPrice") + .HasColumnType("numeric"); + + b.Property("ShortMultiColorPrice") + .HasColumnType("numeric"); + + b.Property("ShortPermanentPrice") + .HasColumnType("numeric"); + + b.Property("WomenHalfCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenLongCutPrice") + .HasColumnType("numeric"); + + b.Property("WomenShortCutPrice") + .HasColumnType("numeric"); + + b.HasKey("UserId"); + + b.HasIndex("ScheduleOwnerId"); + + b.ToTable("BrusherProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("SelectedProfileUserId") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("PrestationId"); + + b.HasIndex("SelectedProfileUserId"); + + b.ToTable("HairCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("HairMultiCutQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Cares") + .HasColumnType("boolean"); + + b.Property("Cut") + .HasColumnType("boolean"); + + b.Property("Dressing") + .HasColumnType("integer"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("Length") + .HasColumnType("integer"); + + b.Property("Shampoo") + .HasColumnType("boolean"); + + b.Property("Tech") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("HairPrestation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.Property("QueryId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PrestationId"); + + b.HasIndex("QueryId"); + + b.ToTable("HairPrestationCollectionItem"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Brand") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ColorId"); + + b.ToTable("HairTaint"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.Property("TaintId") + .HasColumnType("bigint"); + + b.Property("PrestationId") + .HasColumnType("bigint"); + + b.HasKey("TaintId", "PrestationId"); + + b.HasIndex("PrestationId"); + + b.ToTable("HairTaintInstance"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Evolution.Feature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Feature"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FeatureId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FeatureId"); + + b.ToTable("Bug"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeclarationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("LOCALTIMESTAMP"); + + b.Property("DeviceOwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestActivityUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("Model") + .IsRequired() + .HasColumnType("text"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("DeviceId"); + + b.HasIndex("DeviceOwnerId"); + + b.ToTable("DeviceDeclaration"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Depth") + .HasColumnType("numeric"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.Property("Weight") + .HasColumnType("numeric"); + + b.Property("Width") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContextId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("For") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Sender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Announce"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.HasKey("UserId", "NotificationId"); + + b.HasIndex("NotificationId"); + + b.ToTable("DismissClicked"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Instrument"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasAlternateKey("InstrumentId", "OwnerId"); + + b.HasIndex("OwnerId"); + + b.ToTable("InstrumentRating"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.Property("OwnerProfileId") + .HasColumnType("text"); + + b.Property("DjSettingsUserId") + .HasColumnType("text"); + + b.Property("GeneralSettingsUserId") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("TendencyId") + .HasColumnType("bigint"); + + b.HasKey("OwnerProfileId"); + + b.HasIndex("DjSettingsUserId"); + + b.HasIndex("GeneralSettingsUserId"); + + b.ToTable("MusicalPreference"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalTendency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("MusicalTendency"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("SoundCloudId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("DjSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("GeneralSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.Property("InstrumentId") + .HasColumnType("bigint"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("InstrumentId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("Instrumentation"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Property("CreationToken") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrderReference") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaypalPayerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("CreationToken"); + + b.HasIndex("ExecutorId"); + + b.ToTable("PayPalPayment"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Circle"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.Property("MemberId") + .HasColumnType("text"); + + b.Property("CircleId") + .HasColumnType("bigint"); + + b.HasKey("MemberId", "CircleId"); + + b.HasIndex("CircleId"); + + b.ToTable("CircleMembers"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.Property("OwnerId") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("OwnerId", "UserId"); + + b.HasIndex("AddressId"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.Property("HRef") + .HasColumnType("text"); + + b.Property("Method") + .HasColumnType("text"); + + b.Property("BrusherProfileUserId") + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("PayPalPaymentCreationToken") + .HasColumnType("text"); + + b.Property("Rel") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("HRef", "Method"); + + b.HasIndex("BrusherProfileUserId"); + + b.HasIndex("PayPalPaymentCreationToken"); + + b.ToTable("HyperLink"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.PostalAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Country") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street1") + .IsRequired() + .HasColumnType("text"); + + b.Property("Street2") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SiteSkills"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DifferedFileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MediaType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Pitch") + .IsRequired() + .HasColumnType("text"); + + b.Property("SequenceNumber") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("LiveFlow"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Property("Code") + .HasColumnType("text"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Hidden") + .HasColumnType("boolean"); + + b.Property("ModeratorGroupName") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentCode") + .HasColumnType("text"); + + b.Property("Photo") + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SettingsClassName") + .HasColumnType("text"); + + b.Property("UserCreated") + .HasColumnType("text"); + + b.Property("UserModified") + .HasColumnType("text"); + + b.HasKey("Code"); + + b.HasIndex("ParentCode"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FormationSettingsUserId") + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingForId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FormationSettingsUserId"); + + b.HasIndex("PerformerId"); + + b.HasIndex("WorkingForId"); + + b.ToTable("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.ToTable("CommandForm"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Property("PerformerId") + .HasColumnType("text"); + + b.Property("AcceptNotifications") + .HasColumnType("boolean"); + + b.Property("AcceptPublicContact") + .HasColumnType("boolean"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("MaxDailyCost") + .HasColumnType("integer"); + + b.Property("MinDailyCost") + .HasColumnType("integer"); + + b.Property("OrganizationAddressId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("integer"); + + b.Property("SIREN") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseGeoLocalizationToReduceDistanceWithClients") + .HasColumnType("boolean"); + + b.Property("WebSite") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PerformerId"); + + b.HasIndex("OrganizationAddressId"); + + b.ToTable("Performers"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("UserId"); + + b.ToTable("FormationSettings"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EventDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LocationId") + .HasColumnType("bigint"); + + b.Property("LocationType") + .HasColumnType("integer"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("RdvQueries"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.Property("DoesCode") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.Property("Weight") + .HasColumnType("integer"); + + b.HasKey("DoesCode", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserActivities"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.Calendar.Period", b => + { + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Start", "End"); + + b.ToTable("Period"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.EMailing.MailingTemplate", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasMaxLength(65536) + .HasColumnType("character varying(65536)"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("ReplyToAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToSend") + .HasColumnType("integer"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MailingTemplate"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("ActivityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Consent") + .HasColumnType("boolean"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone"); + + b.Property("DateModified") + .HasColumnType("timestamp with time zone"); + + b.Property("Decided") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GitId") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentId") + .IsRequired() + .HasColumnType("text"); + + b.Property("PerformerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Previsional") + .HasColumnType("numeric"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserCreated") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserModified") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ActivityCode"); + + b.HasIndex("ClientId"); + + b.HasIndex("GitId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PerformerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectBuildConfiguration"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Branch") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("GitRepositoryReference"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "TargetUser") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.BlackListed", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("BlackList") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Access.CircleAuthorizationToBlogPost", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Target") + .WithMany("ACL") + .HasForeignKey("BlogPostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Circle", "Allowed") + .WithMany() + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Allowed"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Yavsc.Models.AccountBalance", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithOne("AccountBalance") + .HasForeignKey("Yavsc.Models.AccountBalance", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "PostalAddress") + .WithMany() + .HasForeignKey("PostalAddressId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.BalanceImpact", b => + { + b.HasOne("Yavsc.Models.AccountBalance", "Balance") + .WithMany() + .HasForeignKey("BalanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Balance"); + }); + + modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("BankInfo") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.CommandLine", b => + { + b.HasOne("Yavsc.Models.Billing.Estimate", null) + .WithMany("Bill") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Billing.EstimateTemplate", null) + .WithMany("Bill") + .HasForeignKey("EstimateTemplateId"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.RdvQuery", "Query") + .WithMany() + .HasForeignKey("CommandId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Owner"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany("Posts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogTag", b => + { + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Blog.Comment", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("Yavsc.Models.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.ScheduledEvent", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", null) + .WithMany("Events") + .HasForeignKey("ScheduleOwnerId"); + + b.HasOne("Yavsc.Server.Models.Calendar.Period", "Period") + .WithMany() + .HasForeignKey("PeriodStart", "PeriodEnd") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Period"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatConnection", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Connections") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany("Rooms") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoomAccess", b => + { + b.HasOne("Yavsc.Models.Chat.ChatRoom", "Room") + .WithMany("Moderation") + .HasForeignKey("ChannelName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany("RoomAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Room"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BaseProfile"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", "SelectedProfile") + .WithMany() + .HasForeignKey("SelectedProfileUserId"); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Prestation"); + + b.Navigation("Regularisation"); + + b.Navigation("SelectedProfile"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestationCollectionItem", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany() + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairMultiCutQuery", "Query") + .WithMany("Prestations") + .HasForeignKey("QueryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Query"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaint", b => + { + b.HasOne("Yavsc.Models.Drawing.Color", "Color") + .WithMany() + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairTaintInstance", b => + { + b.HasOne("Yavsc.Models.Haircut.HairPrestation", "Prestation") + .WithMany("Taints") + .HasForeignKey("PrestationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Haircut.HairTaint", "Taint") + .WithMany() + .HasForeignKey("TaintId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prestation"); + + b.Navigation("Taint"); + }); + + modelBuilder.Entity("Yavsc.Models.IT.Fixing.Bug", b => + { + b.HasOne("Yavsc.Models.IT.Evolution.Feature", "False") + .WithMany() + .HasForeignKey("FeatureId"); + + b.Navigation("False"); + }); + + modelBuilder.Entity("Yavsc.Models.Identity.DeviceDeclaration", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "DeviceOwner") + .WithMany("DeviceDeclaration") + .HasForeignKey("DeviceOwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceOwner"); + }); + + modelBuilder.Entity("Yavsc.Models.Market.Service", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Services") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.Announce", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => + { + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notified"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.InstrumentRating", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Instrument") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Profile") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Instrument"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.MusicalPreference", b => + { + b.HasOne("Yavsc.Models.Musical.Profiles.DjSettings", null) + .WithMany("SoundColor") + .HasForeignKey("DjSettingsUserId"); + + b.HasOne("Yavsc.Models.Musical.Profiles.GeneralSettings", null) + .WithMany("SoundColor") + .HasForeignKey("GeneralSettingsUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.Instrumentation", b => + { + b.HasOne("Yavsc.Models.Musical.Instrument", "Tool") + .WithMany() + .HasForeignKey("InstrumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tool"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Executor") + .WithMany() + .HasForeignKey("ExecutorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Executor"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Circles") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.CircleMember", b => + { + b.HasOne("Yavsc.Models.Relationship.Circle", "Circle") + .WithMany("Members") + .HasForeignKey("CircleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Member") + .WithMany("Membership") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Circle"); + + b.Navigation("Member"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Contact", b => + { + b.HasOne("Yavsc.Models.Relationship.PostalAddress", "PostalAddress") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", null) + .WithMany("Book") + .HasForeignKey("ApplicationUserId"); + + b.Navigation("PostalAddress"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.HyperLink", b => + { + b.HasOne("Yavsc.Models.Haircut.BrusherProfile", null) + .WithMany("Links") + .HasForeignKey("BrusherProfileUserId"); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", null) + .WithMany("Links") + .HasForeignKey("PayPalPaymentCreationToken"); + }); + + modelBuilder.Entity("Yavsc.Models.Streaming.LiveFlow", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentCode"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CoWorking", b => + { + b.HasOne("Yavsc.Models.Workflow.Profiles.FormationSettings", null) + .WithMany("CoWorking") + .HasForeignKey("FormationSettingsUserId"); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "WorkingFor") + .WithMany() + .HasForeignKey("WorkingForId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Performer"); + + b.Navigation("WorkingFor"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.CommandForm", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany("Forms") + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.HasOne("Yavsc.Models.Relationship.Location", "OrganizationAddress") + .WithMany() + .HasForeignKey("OrganizationAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Performer") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationAddress"); + + b.Navigation("Performer"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.RdvQuery", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Relationship.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("Location"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.UserActivity", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Does") + .WithMany() + .HasForeignKey("DoesCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "User") + .WithMany("Activity") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Does"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.HasOne("Yavsc.Models.Workflow.Activity", "Context") + .WithMany() + .HasForeignKey("ActivityCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.ApplicationUser", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", "Repository") + .WithMany() + .HasForeignKey("GitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile") + .WithMany() + .HasForeignKey("PerformerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Context"); + + b.Navigation("PerformerProfile"); + + b.Navigation("Regularisation"); + + b.Navigation("Repository"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.ProjectBuildConfiguration", b => + { + b.HasOne("Yavsc.Server.Models.IT.Project", "TargetProject") + .WithMany("Configurations") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TargetProject"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.SourceCode.GitRepositoryReference", b => + { + b.HasOne("Yavsc.Models.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Yavsc.Models.ApplicationUser", b => + { + b.Navigation("AccountBalance") + .IsRequired(); + + b.Navigation("BankInfo"); + + b.Navigation("BlackList"); + + b.Navigation("Book"); + + b.Navigation("Circles"); + + b.Navigation("Connections"); + + b.Navigation("DeviceDeclaration"); + + b.Navigation("Membership"); + + b.Navigation("Posts"); + + b.Navigation("RoomAccess"); + + b.Navigation("Rooms"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.Estimate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Billing.EstimateTemplate", b => + { + b.Navigation("Bill"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.BlogPost", b => + { + b.Navigation("ACL"); + + b.Navigation("Comments"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Yavsc.Models.Blog.Comment", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("Yavsc.Models.Chat.ChatRoom", b => + { + b.Navigation("Moderation"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.BrusherProfile", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairMultiCutQuery", b => + { + b.Navigation("Prestations"); + }); + + modelBuilder.Entity("Yavsc.Models.Haircut.HairPrestation", b => + { + b.Navigation("Taints"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.DjSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Musical.Profiles.GeneralSettings", b => + { + b.Navigation("SoundColor"); + }); + + modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b => + { + b.Navigation("Links"); + }); + + modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Activity", b => + { + b.Navigation("Children"); + + b.Navigation("Forms"); + + b.Navigation("Services"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.PerformerProfile", b => + { + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Yavsc.Models.Workflow.Profiles.FormationSettings", b => + { + b.Navigation("CoWorking"); + }); + + modelBuilder.Entity("Yavsc.Server.Models.IT.Project", b => + { + b.Navigation("Configurations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.cs b/src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.cs new file mode 100644 index 00000000..fa0b59a8 --- /dev/null +++ b/src/Yavsc.Server/Migrations/20250613181510_ActivityNulls.cs @@ -0,0 +1,108 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Yavsc.Migrations +{ + /// + public partial class ActivityNulls : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UserModified", + table: "Activities", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "UserCreated", + table: "Activities", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "SettingsClassName", + table: "Activities", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "Photo", + table: "Activities", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "ModeratorGroupName", + table: "Activities", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UserModified", + table: "Activities", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserCreated", + table: "Activities", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SettingsClassName", + table: "Activities", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Photo", + table: "Activities", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ModeratorGroupName", + table: "Activities", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + } + } +} diff --git a/src/Yavsc.Server/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Yavsc.Server/Migrations/ApplicationDbContextModelSnapshot.cs index 85f8cf30..a9a729ac 100644 --- a/src/Yavsc.Server/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Yavsc.Server/Migrations/ApplicationDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace Yavsc.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("ProductVersion", "9.0.6") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -183,6 +183,56 @@ namespace Yavsc.Migrations b.ToTable("ClientProviderInfo"); }); + modelBuilder.Entity("Yavsc.Abstract.Models.Messaging.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Target") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("body") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("click_action") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("color") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("icon") + .ValueGeneratedOnAdd() + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasDefaultValue("exclam"); + + b.Property("sound") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("tag") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.ToTable("Notification"); + }); + modelBuilder.Entity("Yavsc.Models.Access.Ban", b => { b.Property("Id") @@ -711,7 +761,6 @@ namespace Yavsc.Migrations .HasColumnType("text"); b.Property("Content") - .IsRequired() .HasMaxLength(56224) .HasColumnType("character varying(56224)"); @@ -731,16 +780,11 @@ namespace Yavsc.Migrations .HasColumnType("character varying(1024)"); b.Property("UserCreated") - .IsRequired() .HasColumnType("text"); b.Property("UserModified") - .IsRequired() .HasColumnType("text"); - b.Property("Visible") - .HasColumnType("boolean"); - b.HasKey("Id"); b.HasIndex("AuthorId"); @@ -1602,61 +1646,6 @@ namespace Yavsc.Migrations b.ToTable("DismissClicked"); }); - modelBuilder.Entity("Yavsc.Models.Messaging.Notification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Target") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)"); - - b.Property("body") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)"); - - b.Property("click_action") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)"); - - b.Property("color") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)"); - - b.Property("icon") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(512) - .HasColumnType("character varying(512)") - .HasDefaultValue("exclam"); - - b.Property("sound") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)"); - - b.Property("tag") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("character varying(512)"); - - b.Property("title") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)"); - - b.HasKey("Id"); - - b.ToTable("Notification"); - }); - modelBuilder.Entity("Yavsc.Models.Musical.Instrument", b => { b.Property("Id") @@ -2092,7 +2081,6 @@ namespace Yavsc.Migrations .HasColumnType("boolean"); b.Property("ModeratorGroupName") - .IsRequired() .HasColumnType("text"); b.Property("Name") @@ -2103,22 +2091,18 @@ namespace Yavsc.Migrations .HasColumnType("text"); b.Property("Photo") - .IsRequired() .HasColumnType("text"); b.Property("Rate") .HasColumnType("integer"); b.Property("SettingsClassName") - .IsRequired() .HasColumnType("text"); b.Property("UserCreated") - .IsRequired() .HasColumnType("text"); b.Property("UserModified") - .IsRequired() .HasColumnType("text"); b.HasKey("Code"); @@ -3057,7 +3041,7 @@ namespace Yavsc.Migrations modelBuilder.Entity("Yavsc.Models.Messaging.DismissClicked", b => { - b.HasOne("Yavsc.Models.Messaging.Notification", "Notified") + b.HasOne("Yavsc.Abstract.Models.Messaging.Notification", "Notified") .WithMany() .HasForeignKey("NotificationId") .OnDelete(DeleteBehavior.Cascade) diff --git a/src/Yavsc.Server/Models/ApplicationDbContext.cs b/src/Yavsc.Server/Models/ApplicationDbContext.cs index a4199896..c3876d07 100644 --- a/src/Yavsc.Server/Models/ApplicationDbContext.cs +++ b/src/Yavsc.Server/Models/ApplicationDbContext.cs @@ -40,6 +40,7 @@ namespace Yavsc.Models using Yavsc.Server.Models.Calendar; using Microsoft.EntityFrameworkCore.ChangeTracking; + using Yavsc.Abstract.Models.Messaging; public class ApplicationDbContext : IdentityDbContext { diff --git a/src/Yavsc.Server/Models/Blog/BlogPost.cs b/src/Yavsc.Server/Models/Blog/BlogPost.cs index c866c61a..8e300bf7 100644 --- a/src/Yavsc.Server/Models/Blog/BlogPost.cs +++ b/src/Yavsc.Server/Models/Blog/BlogPost.cs @@ -35,7 +35,7 @@ namespace Yavsc.Models.Blog } [Display(Name="Créateur")] - public string UserCreated + public string? UserCreated { get; set; } @@ -47,7 +47,7 @@ namespace Yavsc.Models.Blog } [Display(Name="Utilisateur ayant modifé le dernier")] - public string UserModified + public string? UserModified { get; set; } diff --git a/src/Yavsc.Server/Models/Messaging/DimissClicked.cs b/src/Yavsc.Server/Models/Messaging/DimissClicked.cs index 3485bb1f..d5db687f 100644 --- a/src/Yavsc.Server/Models/Messaging/DimissClicked.cs +++ b/src/Yavsc.Server/Models/Messaging/DimissClicked.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Yavsc.Abstract.Models.Messaging; using Yavsc.Attributes.Validation; namespace Yavsc.Models.Messaging diff --git a/src/Yavsc.Server/Models/Workflow/Activity.cs b/src/Yavsc.Server/Models/Workflow/Activity.cs index 2ca87aa5..4f062f9b 100644 --- a/src/Yavsc.Server/Models/Workflow/Activity.cs +++ b/src/Yavsc.Server/Models/Workflow/Activity.cs @@ -28,7 +28,7 @@ namespace Yavsc.Models.Workflow [YaStringLength(512)] [Display(Name = "Code du parent")] [ForeignKey("Parent")] - public string ParentCode { get; set; } + public string? ParentCode { get; set; } [Display(Name = "Activité parent"), JsonIgnore] public virtual Activity Parent { get; set; } @@ -41,7 +41,7 @@ namespace Yavsc.Models.Workflow public string Description { get; set; } [Display(Name = "Photo")] - public string Photo { get; set; } + public string? Photo { get; set; } [InverseProperty("Context")] [DisplayAttribute(Name = "Services liés")] @@ -52,7 +52,7 @@ namespace Yavsc.Models.Workflow /// /// [DisplayAttribute(Name = "Groupe de modération")] - public string ModeratorGroupName { get; set; } + public string? ModeratorGroupName { get; set; } /// /// indice de recherche de cette activité @@ -64,7 +64,7 @@ namespace Yavsc.Models.Workflow [DisplayFormatAttribute(DataFormatString="{0}%")] public int Rate { get; set; } [DisplayAttribute(Name = "Classe de paramétrage")] - public string SettingsClassName { get; set; } + public string? SettingsClassName { get; set; } [InverseProperty("Context")] [Display(Name="Formulaires de commande")] @@ -77,7 +77,7 @@ namespace Yavsc.Models.Workflow } [Display(Name="Createur")] - public string UserCreated + public string? UserCreated { get; set; } @@ -89,7 +89,7 @@ namespace Yavsc.Models.Workflow } [Display(Name="Utilisateur ayant modifié le dernier")] - public string UserModified + public string? UserModified { get; set; } diff --git a/src/Yavsc.Server/ViewModels/BlogSpot/BlogPostInputViewModel.cs b/src/Yavsc.Server/ViewModels/BlogSpot/BlogPostInputViewModel.cs index 4f8a10da..526f52e1 100644 --- a/src/Yavsc.Server/ViewModels/BlogSpot/BlogPostInputViewModel.cs +++ b/src/Yavsc.Server/ViewModels/BlogSpot/BlogPostInputViewModel.cs @@ -11,10 +11,11 @@ namespace Yavsc.ViewModels.Blog public string? Photo { get; set; } [StringLength(1024)] + [Required] public string Title { get; set; } [StringLength(56224)] - public string Content { get; set; } + public string? Content { get; set; } [InverseProperty("Target")] [Display(Name="Liste de contrôle d'accès")] diff --git a/src/Yavsc.Server/Yavsc.Server.csproj b/src/Yavsc.Server/Yavsc.Server.csproj index 1d27eab9..0ae56115 100644 --- a/src/Yavsc.Server/Yavsc.Server.csproj +++ b/src/Yavsc.Server/Yavsc.Server.csproj @@ -1,30 +1,30 @@  - net8.0 + net9.0 enable enable 53bd70e8-ff81-497a-847f-a15fd8ea7a09 - + - - + + - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + - + - - + + diff --git "a/src/Yavsc/\"BlogSpot\"" "b/src/Yavsc/\"BlogSpot\"" new file mode 100644 index 00000000..1311bae5 --- /dev/null +++ "b/src/Yavsc/\"BlogSpot\"" @@ -0,0 +1,169 @@ +\dt +select user,password from users; +select user,passwd from users; +select user from users; +select username,pwd from users; +select username,passwd from users; +select username,password from users; +\dT users +\d users +select username,passwd from users; +select username,passd from users; +\d users +select username,passw from users; +\d profiledata +select gregid from profiledata; +select uniqueid,gregid from profiledata; +select uniqueid,username from profile; +select uniqueid,username from profiles; +select uniqueid,gregid from profiledata; +select uniqueid,username from profiles; +select uniqueid,gregid from profiledata; +select uniqueid,gregid from profiledata; +select uniqueid,gregid from profiledata; +select uniqueid,gregid from profiledata; +select uniqueid,gregid from profiledata; +drop table GitRepositoryReference; +\use YavscDev +\use +\? +\use \? +\dt +drop table "GitRepositoryReference"; +drop table "GitRepositoryReference" CASCADE; +exit; +\q +delete from "Project" +; +\q +create database dotnetmvc +; +create user dotnetmvc ; +grant CREATE on paul; +grant admins TO paul; +grant CREATE TO paul; +grant postgres TO paul; +grant paul TO postgres; +commit; +CREATE ROLE baget nocreatedb nocreaterole noreplication; +CREATE ROLE baget nocreatedb nocreaterole noreplication; +CREATE ROLE baget nocreatedb nocreaterole noreplication; +DROP ROLE baget; +commit; +alter role baget with superuser +; +commit; +\dT Project +\dt Project +\dt "Project" +desc "Project" +\? +\d "Project" +\d BlogSpot +\d Blogspot +\d "Blogspot" +\d "BlogSpot" +\d "BlogPost" +\d "BlogPost" +\d "BlogPost" +\d "BlogPost" +\d "BlogPost" +\d AspNetUsers +\d "AspNetUsers" +\dT "AspNetUsers" +update "AspNetUsers" set "LockoutEnable" = false; +\d "AspNetUsers" +\d "AspNetUsers" +update "AspNetUsers" set "LockoutEnabled" = false; +commit ; +\quit +update "AspNetUsers" set "LockoutEnabled" = true; +\s +\d +\dT +\? +\dn +\? +\? +\conninfo +\h create database +\h create user +create user forgejo with login 'ogVZ)f#m85zx'; +create user forgejo with login; +\h alter user +alter user forgejo with PASSWORD 'ogVZ)f#m85zx'; +commit: +commit; +commit; +\h create databse +\h create databse +create database forgejo with owner forgejo; +create user woodpecker with password 'aormb%$98zv q.ClientId == uid && q.Status < QueryStatus.Failed - ).Count(); var toShow = _dbContext.Activities .Include(a => a.Forms) .Include(a => a.Parent) diff --git a/src/Yavsc/Extensions/HostingExtensions.cs b/src/Yavsc/Extensions/HostingExtensions.cs index 0e506813..f1800c7d 100644 --- a/src/Yavsc/Extensions/HostingExtensions.cs +++ b/src/Yavsc/Extensions/HostingExtensions.cs @@ -32,6 +32,7 @@ using Yavsc.ViewModels.Auth; using Yavsc.Server.Helpers; using System.Security.Cryptography; using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Protocols.Configuration; namespace Yavsc.Extensions; @@ -304,7 +305,8 @@ public static class HostingExtensions { var path = builder.Configuration["SigningCert:Path"]; var pass = builder.Configuration["SigningCert:Password"]; - Debug.Assert(path != null); + if (path == null) + throw new InvalidConfigurationException("No signing cert path"); FileInfo certFileInfo = new FileInfo(path); Debug.Assert(certFileInfo.Exists); RSA rsa = RSA.Create(); diff --git a/src/Yavsc/Helpers/AsciiDocHelpers.cs b/src/Yavsc/Helpers/AsciiDocHelpers.cs index bdae4cc1..25bae202 100644 --- a/src/Yavsc/Helpers/AsciiDocHelpers.cs +++ b/src/Yavsc/Helpers/AsciiDocHelpers.cs @@ -70,6 +70,11 @@ namespace Yavsc.Helpers { switch (elt.GetType().FullName) { + case "AsciiDocNet.Monospace": + sb.AppendHtml(""); + Monospace mono = (Monospace)elt; + AllItemsToHtml(sb, mono); + break; case "AsciiDocNet.Link": Link link = (Link)elt; Uri uri; @@ -98,11 +103,8 @@ namespace Yavsc.Helpers case "AsciiDocNet.Strong": sb.AppendHtml(""); - AsciiDocNet.Strong str = (Strong)elt; - foreach (var stritem in str) - { - stritem.ToHtml(sb); - } + Strong str = (Strong)elt; + AllItemsToHtml(sb, str); sb.AppendHtml(""); break; case "AsciiDocNet.InternalAnchor": @@ -138,10 +140,35 @@ namespace Yavsc.Helpers default: string unsupportedType = elt.GetType().FullName; - throw new InvalidProgramException(unsupportedType); + if (elt is InlineContainer inlineContainer) + { + sb.AppendHtml($""); + AllItemsToHtml(sb, inlineContainer); + sb.AppendHtml(""); + } + else if (elt is IInlineElement inlineElement) + { + sb.AppendHtml($""); + RenderLitteral(inlineElement, sb); + sb.AppendHtml(""); + } + else + { + throw new InvalidProgramException(unsupportedType); + } + break; } } + private static void AllItemsToHtml(IHtmlContentBuilder sb, InlineContainer mono) + { + foreach (var item in mono) + { + item.ToHtml(sb); + } + sb.AppendHtml(""); + } + private static void RenderLitteral(IInlineElement elt, IHtmlContentBuilder sb) { var tl = elt as TextLiteral; @@ -173,39 +200,39 @@ namespace Yavsc.Helpers return contentbuilder; } -/* - public static IHtmlContent AsciiDocFor(this IHtmlHelper html, - Expression> expression) - { - string ascii = html.ValueFor(expression, "{0}"); - if (string.IsNullOrWhiteSpace(ascii)) - return new HtmlString(string.Empty); - Document document = Document.Parse(ascii); - var htmlDoc = document.ToHtml(); - var span = new TagBuilder("p") { TagRenderMode = TagRenderMode.SelfClosing }; - span.InnerHtml.AppendHtml(htmlDoc); - return span.RenderBody(); - } + /* + public static IHtmlContent AsciiDocFor(this IHtmlHelper html, + Expression> expression) + { + string ascii = html.ValueFor(expression, "{0}"); + if (string.IsNullOrWhiteSpace(ascii)) + return new HtmlString(string.Empty); + Document document = Document.Parse(ascii); + var htmlDoc = document.ToHtml(); + var span = new TagBuilder("p") { TagRenderMode = TagRenderMode.SelfClosing }; + span.InnerHtml.AppendHtml(htmlDoc); + return span.RenderBody(); + } - public static string AsciiDoc(IHtmlHelper htmlHelper, string text) - { - return AsciiDoc(htmlHelper, text, null); - } + public static string AsciiDoc(IHtmlHelper htmlHelper, string text) + { + return AsciiDoc(htmlHelper, text, null); + } - private static string AsciiDoc(IHtmlHelper htmlHelper, string text, object htmlAttributes) - { - // Create tag builder - var builder = new TagBuilder("div"); - var document = Document.Parse(text); + private static string AsciiDoc(IHtmlHelper htmlHelper, string text, object htmlAttributes) + { + // Create tag builder + var builder = new TagBuilder("div"); + var document = Document.Parse(text); - // builder.InnerHtml = . + // builder.InnerHtml = . - // Add attributes - builder.MergeAttribute("class", "ascii"); - builder.MergeAttributes(new RouteValueDictionary(htmlAttributes)); + // Add attributes + builder.MergeAttribute("class", "ascii"); + builder.MergeAttributes(new RouteValueDictionary(htmlAttributes)); - // Render tag - return builder.ToString(); - } */ + // Render tag + return builder.ToString(); + } */ } } diff --git a/src/Yavsc/Helpers/ControllerHelpers.cs b/src/Yavsc/Helpers/ControllerHelpers.cs index 6b89b104..eda80231 100644 --- a/src/Yavsc/Helpers/ControllerHelpers.cs +++ b/src/Yavsc/Helpers/ControllerHelpers.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; -using Yavsc.Models.Messaging; +using Yavsc.Abstract.Models.Messaging; namespace Yavsc.Helpers { diff --git a/src/Yavsc/Makefile b/src/Yavsc/Makefile index aafc43ac..e3c0a617 100644 --- a/src/Yavsc/Makefile +++ b/src/Yavsc/Makefile @@ -1,36 +1,33 @@ DESTDIR=/srv/www/yavsc -HOSTING=localhost -ASPNET_LOG_LEVEL=debug -SOURCE_DIR=../.. +CONFIGURATION=Release USER=www-data -HOSTING_PRE=yavsv.pschneider.fr -CONFIGURATION=Debug -SERVICE_PRE=Yavsc +SERVICE_PROD=yavsc +DOTNET_FRAMEWORK=net9.0 all: dotnet build showConfig: - @echo HOSTING_PRE: $(USER)@$(HOSTING_PRE) @echo CONFIGURATION: $(CONFIGURATION) @echo DESTDIR: $(DESTDIR) - @echo SERVICE_PRE: $(SERVICE_PRE) + @echo SERVICE_PROD: $(SERVICE_PROD) publish: ASPNETCORE_ENV=$(CONFIGURATION) dotnet publish -pushInPre: publish - sudo service $(SERVICE_PRE) stop - sudo cp -a bin/Debug/net7.0/publish/* $(DESTDIR) +install_service: + sudo cp ../../contrib/yavsc.service /etc/systemd/system + sudo systemctl enable yavsc + +pushInProd: publish + sudo systemctl stop $(SERVICE_PROD) + sudo cp -a bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish/* $(DESTDIR) sudo chown -R $(USER) $(DESTDIR) sudo sync - sudo service $(SERVICE_PRE) start + sudo systemctl start $(SERVICE_PROD) %.min.js: %.js jsmin < $^ > $@ %.min.css: %.css jsmin < $^ > $@ - -%.Designer.cs: %.resx - strongresbuildercli -l -p -t -r "Yavsc.Resources." $^ diff --git a/src/Yavsc/Views/Home/Index.cshtml b/src/Yavsc/Views/Home/Index.cshtml index 1fd4b24f..f2580e3e 100755 --- a/src/Yavsc/Views/Home/Index.cshtml +++ b/src/Yavsc/Views/Home/Index.cshtml @@ -80,11 +80,6 @@
  • announces
  • } - @if ((int)ViewData["HaircutCommandCount"]>0) { -
  • - basket(@ViewData["HaircutCommandCount"])
  • - } - } @section header { diff --git a/src/Yavsc/Views/Notifications/Create.cshtml b/src/Yavsc/Views/Notifications/Create.cshtml index 90d5fc40..e95909b0 100644 --- a/src/Yavsc/Views/Notifications/Create.cshtml +++ b/src/Yavsc/Views/Notifications/Create.cshtml @@ -1,4 +1,4 @@ -@model Yavsc.Models.Messaging.Notification +@model Notification @{ ViewData["Title"] = "Create"; diff --git a/src/Yavsc/Views/Notifications/Delete.cshtml b/src/Yavsc/Views/Notifications/Delete.cshtml index e8f0c8aa..ea4eec33 100644 --- a/src/Yavsc/Views/Notifications/Delete.cshtml +++ b/src/Yavsc/Views/Notifications/Delete.cshtml @@ -1,4 +1,4 @@ -@model Yavsc.Models.Messaging.Notification +@model Notification @{ ViewData["Title"] = "Delete"; diff --git a/src/Yavsc/Views/Notifications/Details.cshtml b/src/Yavsc/Views/Notifications/Details.cshtml index b6d3eaa2..c2ef4206 100644 --- a/src/Yavsc/Views/Notifications/Details.cshtml +++ b/src/Yavsc/Views/Notifications/Details.cshtml @@ -1,4 +1,4 @@ -@model Yavsc.Models.Messaging.Notification +@model Notification @{ ViewData["Title"] = "Details"; diff --git a/src/Yavsc/Views/Notifications/Edit.cshtml b/src/Yavsc/Views/Notifications/Edit.cshtml index 83312ca0..6fde0685 100644 --- a/src/Yavsc/Views/Notifications/Edit.cshtml +++ b/src/Yavsc/Views/Notifications/Edit.cshtml @@ -1,4 +1,4 @@ -@model Yavsc.Models.Messaging.Notification +@model Notification @{ ViewData["Title"] = "Edit"; diff --git a/src/Yavsc/Views/Notifications/Index.cshtml b/src/Yavsc/Views/Notifications/Index.cshtml index e3bd70c4..03abae79 100644 --- a/src/Yavsc/Views/Notifications/Index.cshtml +++ b/src/Yavsc/Views/Notifications/Index.cshtml @@ -1,4 +1,4 @@ -@model IEnumerable +@model IEnumerable @{ ViewData["Title"] = "Index"; diff --git a/src/Yavsc/Views/Shared/_LoginPartial.cshtml b/src/Yavsc/Views/Shared/_LoginPartial.cshtml index 01f02585..1288c981 100644 --- a/src/Yavsc/Views/Shared/_LoginPartial.cshtml +++ b/src/Yavsc/Views/Shared/_LoginPartial.cshtml @@ -18,7 +18,6 @@ diff --git a/src/Yavsc/Views/_ViewImports.cshtml b/src/Yavsc/Views/_ViewImports.cshtml index 8b046214..64f07170 100755 --- a/src/Yavsc/Views/_ViewImports.cshtml +++ b/src/Yavsc/Views/_ViewImports.cshtml @@ -11,6 +11,7 @@ @using Yavsc.Models.Auth; @using Yavsc.Models.Identity; @using Yavsc.Models.Access; +@using Yavsc.Abstract.Models.Messaging; @using Yavsc.Billing; @using Yavsc.Server.Models.Calendar; @using Yavsc.ViewModels.Blog; @@ -28,7 +29,6 @@ @using Microsoft.AspNetCore.Html; @using Microsoft.AspNetCore.Identity; @using Yavsc.Helpers; - @using PayPal.PayPalAPIInterfaceService.Model; @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/Yavsc/Yavsc.csproj b/src/Yavsc/Yavsc.csproj index 301e6c55..7454edb4 100644 --- a/src/Yavsc/Yavsc.csproj +++ b/src/Yavsc/Yavsc.csproj @@ -1,6 +1,6 @@  - net8.0 + net9.0 enable enable WTFPL @@ -15,33 +15,34 @@ - - + + - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + - - - - - - + + + + + + - +
    +
    diff --git a/src/Yavsc/data/key-afbdf233-abc3-4762-865b-884187518d95.xml b/src/Yavsc/data/key-afbdf233-abc3-4762-865b-884187518d95.xml new file mode 100644 index 00000000..eb012836 --- /dev/null +++ b/src/Yavsc/data/key-afbdf233-abc3-4762-865b-884187518d95.xml @@ -0,0 +1,16 @@ + + + 2025-06-13T12:15:54.5621476Z + 2025-06-13T12:15:54.558788Z + 2025-09-11T12:15:54.558788Z + + + + + + + mNS2X6pB+1DLQ8JaiXInlPJF6xFGLIRrMtgLF1oRfJ/60kCHY7OJuu/NOD18mxOTQEUj/IoHBM3PCAnGwiRG4Q== + + + + \ No newline at end of file diff --git a/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj b/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj index 439bb179..10851d3f 100644 --- a/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj +++ b/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj @@ -1,8 +1,14 @@ + + net9.0 + enable + enable + + - + @@ -12,10 +18,4 @@ - - net8.0 - enable - enable - - diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.babelrc.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.babelrc.js new file mode 100644 index 00000000..51399697 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.babelrc.js @@ -0,0 +1,12 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + loose: true, + bugfixes: true, + modules: false + } + ] + ] +}; diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bower.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bower.json index b8d11ac9..b2879422 100644 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bower.json +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bower.json @@ -1,44 +1,15 @@ { "name": "bootstrap", - "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", - "keywords": [ - "css", - "js", - "less", - "mobile-first", - "responsive", - "front-end", - "framework", - "web" - ], - "homepage": "http://getbootstrap.com", - "license": "MIT", - "moduleType": "globals", - "main": [ - "less/bootstrap.less", - "dist/js/bootstrap.js" - ], - "ignore": [ - "/.*", - "_config.yml", - "CNAME", - "composer.json", - "CONTRIBUTING.md", - "docs", - "js/tests", - "test-infra" - ], - "dependencies": { - "jquery": ">= 1.9.1" - }, - "version": "3.3.5", - "_release": "3.3.5", + "homepage": "https://github.com/twbs/bootstrap", + "version": "5.3.6", + "_release": "5.3.6", "_resolution": { "type": "version", - "tag": "v3.3.5", - "commit": "16b48259a62f576e52c903c476bd42b90ab22482" + "tag": "v5.3.6", + "commit": "f849680d16a9695c9a6c9c062d6cff55ddcf071e" }, "_source": "https://github.com/twbs/bootstrap.git", - "_target": "3.3.5", - "_originalSource": "bootstrap" + "_target": "^5.3.6", + "_originalSource": "bootstrap", + "_direct": true } \ No newline at end of file diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.browserslistrc b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.browserslistrc new file mode 100644 index 00000000..cddd2300 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.browserslistrc @@ -0,0 +1,12 @@ +# https://github.com/browserslist/browserslist#readme + +>= 0.5% +last 2 major versions +not dead +Chrome >= 60 +Firefox >= 60 +Firefox ESR +iOS >= 12 +Safari >= 12 +not Explorer <= 11 +not kaios <= 2.5 # fix floating label issues in Firefox (see https://github.com/postcss/autoprefixer/issues/1533) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bundlewatch.config.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bundlewatch.config.json new file mode 100644 index 00000000..6f680664 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.bundlewatch.config.json @@ -0,0 +1,66 @@ +{ + "files": [ + { + "path": "./dist/css/bootstrap-grid.css", + "maxSize": "6.5 kB" + }, + { + "path": "./dist/css/bootstrap-grid.min.css", + "maxSize": "6.0 kB" + }, + { + "path": "./dist/css/bootstrap-reboot.css", + "maxSize": "3.5 kB" + }, + { + "path": "./dist/css/bootstrap-reboot.min.css", + "maxSize": "3.25 kB" + }, + { + "path": "./dist/css/bootstrap-utilities.css", + "maxSize": "11.75 kB" + }, + { + "path": "./dist/css/bootstrap-utilities.min.css", + "maxSize": "10.75 kB" + }, + { + "path": "./dist/css/bootstrap.css", + "maxSize": "32.5 kB" + }, + { + "path": "./dist/css/bootstrap.min.css", + "maxSize": "30.25 kB" + }, + { + "path": "./dist/js/bootstrap.bundle.js", + "maxSize": "43.0 kB" + }, + { + "path": "./dist/js/bootstrap.bundle.min.js", + "maxSize": "23.5 kB" + }, + { + "path": "./dist/js/bootstrap.esm.js", + "maxSize": "28.0 kB" + }, + { + "path": "./dist/js/bootstrap.esm.min.js", + "maxSize": "18.25 kB" + }, + { + "path": "./dist/js/bootstrap.js", + "maxSize": "28.75 kB" + }, + { + "path": "./dist/js/bootstrap.min.js", + "maxSize": "16.25 kB" + } + ], + "ci": { + "trackBranches": [ + "main", + "v4-dev" + ] + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.cspell.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.cspell.json new file mode 100644 index 00000000..d2434c30 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.cspell.json @@ -0,0 +1,131 @@ +{ + "version": "0.2", + "words": [ + "affordance", + "allowfullscreen", + "Analyser", + "autohide", + "autohiding", + "autoplay", + "autoplays", + "autoplaying", + "blazingly", + "Blockquotes", + "Bootstrappers", + "borderless", + "Brotli", + "browserslist", + "browserslistrc", + "btncheck", + "btnradio", + "callout", + "callouts", + "camelCase", + "clearfix", + "Codesniffer", + "combinator", + "Contentful", + "Cpath", + "Crossfade", + "crossfading", + "cssgrid", + "Csvg", + "Datalists", + "Deque", + "discoverability", + "docsearch", + "docsref", + "dropend", + "dropleft", + "dropright", + "dropstart", + "dropup", + "dgst", + "errorf", + "favicon", + "favicons", + "fieldsets", + "flexbox", + "fullscreen", + "getbootstrap", + "Grayscale", + "Hoverable", + "hreflang", + "hstack", + "importmap", + "jsdelivr", + "Jumpstart", + "keyframes", + "libera", + "libman", + "Libsass", + "lightboxes", + "Lowercased", + "markdownify", + "mediaqueries", + "minifiers", + "misfunction", + "mkdir", + "monospace", + "mouseleave", + "navbars", + "navs", + "Neue", + "noindex", + "Noto", + "offcanvas", + "offcanvases", + "Packagist", + "popperjs", + "prebuild", + "prefersreducedmotion", + "prepended", + "printf", + "rects", + "relref", + "rgba", + "roboto", + "RTLCSS", + "ruleset", + "sassrc", + "screenreaders", + "scrollbars", + "scrollspy", + "Segoe", + "semibold", + "socio", + "srcset", + "stackblitz", + "stickied", + "Stylelint", + "subnav", + "tabbable", + "textareas", + "toggleable", + "topbar", + "touchend", + "twbs", + "unitless", + "unstylable", + "unstyled", + "Uppercased", + "urlize", + "urlquery", + "vbtn", + "viewports", + "Vite", + "vstack", + "walkthroughs", + "WCAG", + "zindex" + ], + "language": "en-US", + "ignorePaths": [ + ".cspell.json", + "dist/", + "*.min.*", + "**/*rtl*", + "**/tests/**" + ], + "useGitignore": true +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.editorconfig b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.editorconfig new file mode 100644 index 00000000..f29d257c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.editorconfig @@ -0,0 +1,11 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintignore b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintignore new file mode 100644 index 00000000..e4216148 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintignore @@ -0,0 +1,9 @@ +**/*.min.js +**/dist/ +**/vendor/ +/_site/ +/site/public/ +/js/coverage/ +/site/static/sw.js +/site/static/docs/**/assets/sw.js +/site/layouts/partials/ diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintrc.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintrc.json new file mode 100644 index 00000000..017a6d13 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.eslintrc.json @@ -0,0 +1,240 @@ +{ + "root": true, + "extends": [ + "plugin:import/errors", + "plugin:import/warnings", + "plugin:unicorn/recommended", + "xo", + "xo/browser" + ], + "rules": { + "arrow-body-style": "off", + "capitalized-comments": "off", + "comma-dangle": [ + "error", + "never" + ], + "import/extensions": [ + "error", + "ignorePackages", + { + "js": "always" + } + ], + "import/first": "error", + "import/newline-after-import": "error", + "import/no-absolute-path": "error", + "import/no-amd": "error", + "import/no-cycle": [ + "error", + { + "ignoreExternal": true + } + ], + "import/no-duplicates": "error", + "import/no-extraneous-dependencies": "error", + "import/no-mutable-exports": "error", + "import/no-named-as-default": "error", + "import/no-named-as-default-member": "error", + "import/no-named-default": "error", + "import/no-self-import": "error", + "import/no-unassigned-import": [ + "error" + ], + "import/no-useless-path-segments": "error", + "import/order": "error", + "indent": [ + "error", + 2, + { + "MemberExpression": "off", + "SwitchCase": 1 + } + ], + "logical-assignment-operators": "off", + "max-params": [ + "warn", + 5 + ], + "multiline-ternary": [ + "error", + "always-multiline" + ], + "new-cap": [ + "error", + { + "properties": false + } + ], + "no-console": "error", + "no-negated-condition": "off", + "object-curly-spacing": [ + "error", + "always" + ], + "operator-linebreak": [ + "error", + "after" + ], + "prefer-object-has-own": "off", + "prefer-template": "error", + "semi": [ + "error", + "never" + ], + "strict": "error", + "unicorn/explicit-length-check": "off", + "unicorn/filename-case": "off", + "unicorn/no-anonymous-default-export": "off", + "unicorn/no-array-callback-reference": "off", + "unicorn/no-array-method-this-argument": "off", + "unicorn/no-null": "off", + "unicorn/no-typeof-undefined": "off", + "unicorn/no-unused-properties": "error", + "unicorn/numeric-separators-style": "off", + "unicorn/prefer-array-flat": "off", + "unicorn/prefer-at": "off", + "unicorn/prefer-dom-node-dataset": "off", + "unicorn/prefer-module": "off", + "unicorn/prefer-query-selector": "off", + "unicorn/prefer-spread": "off", + "unicorn/prefer-string-raw": "off", + "unicorn/prefer-string-replace-all": "off", + "unicorn/prefer-structured-clone": "off", + "unicorn/prevent-abbreviations": "off" + }, + "overrides": [ + { + "files": [ + "build/**" + ], + "env": { + "browser": false, + "node": true + }, + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "no-console": "off", + "unicorn/prefer-top-level-await": "off" + } + }, + { + "files": [ + "js/**" + ], + "parserOptions": { + "sourceType": "module" + } + }, + { + "files": [ + "js/tests/*.js", + "js/tests/integration/rollup*.js" + ], + "env": { + "node": true + }, + "parserOptions": { + "sourceType": "script" + } + }, + { + "files": [ + "js/tests/unit/**" + ], + "env": { + "jasmine": true + }, + "rules": { + "no-console": "off", + "unicorn/consistent-function-scoping": "off", + "unicorn/no-useless-undefined": "off", + "unicorn/prefer-add-event-listener": "off" + } + }, + { + "files": [ + "js/tests/visual/**" + ], + "plugins": [ + "html" + ], + "settings": { + "html/html-extensions": [ + ".html" + ] + }, + "rules": { + "no-console": "off", + "no-new": "off", + "unicorn/no-array-for-each": "off" + } + }, + { + "files": [ + "scss/tests/**" + ], + "env": { + "node": true + }, + "parserOptions": { + "sourceType": "script" + } + }, + { + "files": [ + "site/**" + ], + "env": { + "browser": true, + "node": false + }, + "parserOptions": { + "sourceType": "script", + "ecmaVersion": 2019 + }, + "rules": { + "no-new": "off", + "unicorn/no-array-for-each": "off" + } + }, + { + "files": [ + "site/src/assets/application.js", + "site/src/assets/partials/*.js", + "site/src/assets/search.js", + "site/src/assets/snippets.js", + "site/src/assets/stackblitz.js", + "site/src/plugins/*.js" + ], + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 2020 + } + }, + { + "files": [ + "**/*.md" + ], + "plugins": [ + "markdown" + ], + "processor": "markdown/markdown" + }, + { + "files": [ + "**/*.md/*.js", + "**/*.md/*.mjs" + ], + "extends": "plugin:markdown/recommended-legacy", + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "unicorn/prefer-node-protocol": "off" + } + } + ] +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.gitattributes b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.gitattributes new file mode 100644 index 00000000..40b1c374 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.gitattributes @@ -0,0 +1,8 @@ +# Enforce Unix newlines +* text=auto eol=lf + +# Don't diff or textually merge source maps +*.map binary + +bootstrap.css linguist-vendored=false +bootstrap.js linguist-vendored=false diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CODEOWNERS b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CODEOWNERS new file mode 100644 index 00000000..7d3fa990 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CODEOWNERS @@ -0,0 +1,3 @@ +*.js @twbs/js-review +*.css @twbs/css-review +*.scss @twbs/css-review diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CONTRIBUTING.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CONTRIBUTING.md new file mode 100644 index 00000000..a37b0121 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/CONTRIBUTING.md @@ -0,0 +1,258 @@ +# Contributing to Bootstrap + +Looking to contribute something to Bootstrap? **Here’s how you can help.** + +Please take a moment to review this document in order to make the contribution +process easy and effective for everyone involved. + +Following these guidelines helps to communicate that you respect the time of +the developers managing and developing this open source project. In return, +they should reciprocate that respect in addressing your issue or assessing +patches and features. + + +## Using the issue tracker + +The [issue tracker](https://github.com/twbs/bootstrap/issues) is +the preferred channel for [bug reports](#bug-reports), [features requests](#feature-requests) +and [submitting pull requests](#pull-requests), but please respect the following +restrictions: + +- Please **do not** use the issue tracker for personal support requests. Stack Overflow ([`bootstrap-5`](https://stackoverflow.com/questions/tagged/bootstrap-5) tag), [our GitHub Discussions](https://github.com/twbs/bootstrap/discussions) or [IRC](/README.md#community) are better places to get help. + +- Please **do not** derail or troll issues. Keep the discussion on topic and + respect the opinions of others. + +- Please **do not** post comments consisting solely of "+1" or ":thumbsup:". + Use [GitHub's "reactions" feature](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) + instead. We reserve the right to delete comments which violate this rule. + +- Please **do not** open issues regarding the official themes offered on . + Instead, please email any questions or feedback regarding those themes to `themes AT getbootstrap DOT com`. + + +## Issues assignment + +The core team will be looking at the open issues, analyze them, and provide guidance on how to proceed. **Issues won’t be assigned to anyone outside the core team.** However, contributors are welcome to participate in the discussion and provide their input on how to best solve the issue, and even submit a PR if they want to. Please wait that the issue is ready to be worked on before submitting a PR, we don’t want to waste your time. + +Please keep in mind that the core team is small, has limited resources and that we are not always able to respond immediately. We will try to provide feedback as soon as possible, but please be patient. If you don’t get a response immediately, it doesn’t mean that we are ignoring you or that we don’t care about your issue or PR. We will get back to you as soon as we can. + + +## Issues and labels + +Our bug tracker utilizes several labels to help organize and identify issues. Here’s what they represent and how we use them: + +- `browser bug` - Issues that are reported to us, but actually are the result of a browser-specific bug. These are diagnosed with reduced test cases and result in an issue opened on that browser's own bug tracker. +- `confirmed` - Issues that have been confirmed with a reduced test case and identify a bug in Bootstrap. +- `css` - Issues stemming from our compiled CSS or source Sass files. +- `docs` - Issues for improving or updating our documentation. +- `examples` - Issues involving the example templates included in our docs. +- `feature` - Issues asking for a new feature to be added, or an existing one to be extended or modified. New features require a minor version bump (e.g., `v3.0.0` to `v3.1.0`). +- `build` - Issues with our build system, which is used to run all our tests, concatenate and compile source files, and more. +- `help wanted` - Issues we need or would love help from the community to resolve. +- `js` - Issues stemming from our compiled or source JavaScript files. +- `meta` - Issues with the project itself or our GitHub repository. + +For a complete look at our labels, see the [project labels page](https://github.com/twbs/bootstrap/labels). + + +## Bug reports + +A bug is a _demonstrable problem_ that is caused by the code in the repository. +Good bug reports are extremely helpful, so thanks! + +Guidelines for bug reports: + +0. **[Validate your HTML](https://html5.validator.nu/)** to ensure your + problem isn’t caused by a simple error in your own code. + +1. **Use the GitHub issue search** — check if the issue has already been + reported. + +2. **Check if the issue has been fixed** — try to reproduce it using the + latest `main` (or `v4-dev` branch if the issue is about v4) in the repository. + +3. **Isolate the problem** — ideally create a [reduced test + case](https://css-tricks.com/reduced-test-cases/) and a live example. + These [v4 CodePen](https://codepen.io/team/bootstrap/pen/yLabNQL) and [v5 CodePen](https://codepen.io/team/bootstrap/pen/qBamdLj) are helpful templates. + + +A good bug report shouldn’t leave others needing to chase you up for more +information. Please try to be as detailed as possible in your report. What is +your environment? What steps will reproduce the issue? What browser(s) and OS +experience the problem? Do other browsers show the bug differently? What +would you expect to be the outcome? All these details will help people to fix +any potential bugs. + +Example: + +> Short and descriptive example bug report title +> +> A summary of the issue and the browser/OS environment in which it occurs. If +> suitable, include the steps required to reproduce the bug. +> +> 1. This is the first step +> 2. This is the second step +> 3. Further steps, etc. +> +> `` - a link to the reduced test case +> +> Any other information you want to share that is relevant to the issue being +> reported. This might include the lines of code that you have identified as +> causing the bug, and potential solutions (and your opinions on their +> merits). + +### Reporting upstream browser bugs + +Sometimes bugs reported to us are actually caused by bugs in the browser(s) themselves, not bugs in Bootstrap per se. + +| Vendor(s) | Browser(s) | Rendering engine | Bug reporting website(s) | Notes | +| ------------- | ---------------------------- | ---------------- | ------------------------------------------------------ | -------------------------------------------------------- | +| Mozilla | Firefox | Gecko | | "Core" is normally the right product option to choose. | +| Apple | Safari | WebKit | | In Apple’s bug reporter, choose "Safari" as the product. | +| Google, Opera | Chrome, Chromium, Opera v15+ | Blink | | Click the "New issue" button. | +| Microsoft | Edge | Blink | | Go to "Help > Send Feedback" from the browser | + + +## Feature requests + +Feature requests are welcome. But take a moment to find out whether your idea +fits with the scope and aims of the project. It’s up to _you_ to make a strong +case to convince the project’s developers of the merits of this feature. Please +provide as much detail and context as possible. + + +## Pull requests + +Good pull requests—patches, improvements, new features—are a fantastic +help. They should remain focused in scope and avoid containing unrelated +commits. + +**Please ask first** before embarking on any **significant** pull request (e.g. +implementing features, refactoring code, porting to a different language), +otherwise you risk spending a lot of time working on something that the +project’s developers might not want to merge into the project. For trivial +things, or things that don’t require a lot of your time, you can go ahead and +make a PR. + +Please adhere to the [coding guidelines](#code-guidelines) used throughout the +project (indentation, accurate comments, etc.) and any other requirements +(such as test coverage). + +**Do not edit `bootstrap.css` or `bootstrap.js`, and do not commit +any dist files (`dist/` or `js/dist`).** Those files are automatically generated by our build tools. You should +edit the source files in [`/bootstrap/scss/`](https://github.com/twbs/bootstrap/tree/main/scss) +and/or [`/bootstrap/js/src/`](https://github.com/twbs/bootstrap/tree/main/js/src) instead. + +Similarly, when contributing to Bootstrap’s documentation, you should edit the +documentation source files in +[the `/bootstrap/site/content/docs/` directory of the `main` branch](https://github.com/twbs/bootstrap/tree/main/site/content/docs). +**Do not edit the `gh-pages` branch.** That branch is generated from the +documentation source files and is managed separately by the Bootstrap Core Team. + +Adhering to the following process is the best way to get your work +included in the project: + +1. [Fork](https://help.github.com/articles/fork-a-repo/) the project, clone your fork, + and configure the remotes: + + ```bash + # Clone your fork of the repo into the current directory + git clone https://github.com//bootstrap.git + # Navigate to the newly cloned directory + cd bootstrap + # Assign the original repo to a remote called "upstream" + git remote add upstream https://github.com/twbs/bootstrap.git + ``` + +2. If you cloned a while ago, get the latest changes from upstream: + + ```bash + git checkout main + git pull upstream main + ``` + +3. Install or update project dependencies with npm: + + ```bash + npm install + ``` + +4. Create a new topic branch (off the main project development branch) to + contain your feature, change, or fix: + + ```bash + git checkout -b + ``` + +5. Commit your changes in logical chunks. Please adhere to these [git commit + message guidelines](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) + or your code is unlikely be merged into the main project. Use Git’s + [interactive rebase](https://help.github.com/articles/about-git-rebase/) + feature to tidy up your commits before making them public. + +6. Ensure your changes compile the dist CSS and JS files in the `dist/` directory. Verify + the build succeeds locally without errors. + + ```bash + npm run dist + ``` + +7. Locally merge (or rebase) the upstream development branch into your topic branch: + + ```bash + git pull [--rebase] upstream main + ``` + +8. Commit your changes, but **do not push compiled CSS and JS files in `dist` and `js/dist`**. + Push your topic branch up to your fork: + + ```bash + git push origin + ``` + +9. [Open a pull request](https://help.github.com/articles/about-pull-requests/) + with a clear title and description against the `main` branch. + +**IMPORTANT**: By submitting a patch, you agree to allow the project owners to +license your work under the terms of the [MIT License](../LICENSE) (if it +includes code changes) and under the terms of the +[Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/) +(if it includes documentation changes). + + +## Code guidelines + +### HTML + +[Adhere to the Code Guide.](https://codeguide.co/#html) + +- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags). +- Use CDNs and HTTPS for third-party JS when possible. We don’t use protocol-relative URLs in this case because they break when viewing the page locally via `file://`. +- Use [WAI-ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) attributes in documentation examples to promote accessibility. + +### CSS + +[Adhere to the Code Guide.](https://codeguide.co/#css) + +- When feasible, default color palettes should comply with [WCAG color contrast guidelines](https://www.w3.org/TR/WCAG/#distinguishable). +- Except in rare cases, don’t remove default `:focus` styles (via e.g. `outline: none;`) without providing alternative styles. See [this A11Y Project post](https://www.a11yproject.com/posts/2013-01-25-never-remove-css-outlines/) for more details. + +### JS + +- No semicolons (in client-side JS) +- 2 spaces (no tabs) +- strict mode +- "Attractive" + +### Checking coding style + +Run `npm run test` before committing to ensure your changes follow our coding standards. + + +## License + +By contributing your code, you agree to license your contribution under the [MIT License](../LICENSE). +By contributing to the documentation, you agree to license your contribution under the [Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/). + +Prior to v3.1.0, Bootstrap’s code was released under the Apache License v2.0. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/bug_report.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..3e3d6b9e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,62 @@ +name: Report a bug +description: Tell us about a bug or issue you may have identified in Bootstrap. +title: "Provide a general summary of the issue" +labels: [bug] +assignees: "-" +body: + - type: checkboxes + attributes: + label: Prerequisites + description: Take a couple minutes to help our maintainers work faster. + options: + - label: I have [searched](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue) for duplicate or closed issues + required: true + - label: I have [validated](https://html5.validator.nu/) any HTML to avoid common problems + required: true + - label: I have read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md) + required: true + - type: textarea + id: what-happened + attributes: + label: Describe the issue + description: Provide a summary of the issue and what you expected to happen, including specific steps to reproduce. + validations: + required: true + - type: textarea + id: reduced-test-case + attributes: + label: Reduced test cases + description: Include links [reduced test case](https://css-tricks.com/reduced-test-cases/) links or suggested fixes using CodePen ([v4 template](https://codepen.io/team/bootstrap/pen/yLabNQL) or [v5 template](https://codepen.io/team/bootstrap/pen/qBamdLj)). + validations: + required: true + - type: dropdown + id: os + attributes: + label: What operating system(s) are you seeing the problem on? + multiple: true + options: + - Windows + - macOS + - Android + - iOS + - Linux + validations: + required: true + - type: dropdown + id: browser + attributes: + label: What browser(s) are you seeing the problem on? + multiple: true + options: + - Chrome + - Safari + - Firefox + - Microsoft Edge + - Opera + - type: input + id: version + attributes: + label: What version of Bootstrap are you using? + placeholder: "e.g., v5.1.0 or v4.5.2" + validations: + required: true diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/config.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..f1520711 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: Ask the community + url: https://github.com/twbs/bootstrap/discussions/new + about: Ask and discuss questions with other Bootstrap community members. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/feature_request.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..4b757b1d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,29 @@ +name: Feature request +description: Suggest new or updated features to include in Bootstrap. +title: "Suggest a new feature" +labels: [feature] +assignees: [] +body: + - type: checkboxes + attributes: + label: Prerequisites + description: Take a couple minutes to help our maintainers work faster. + options: + - label: I have [searched](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue) for duplicate or closed feature requests + required: true + - label: I have read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md) + required: true + - type: textarea + id: proposal + attributes: + label: Proposal + description: Provide detailed information for what we should add, including relevant links to prior art, screenshots, or live demos whenever possible. + validations: + required: true + - type: textarea + id: motivation + attributes: + label: Motivation and context + description: Tell us why this change is needed or helpful, and what problems it may help solve. + validations: + required: true diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/PULL_REQUEST_TEMPLATE.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..04df74f3 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,38 @@ +### Description + + + +### Motivation & Context + + + +### Type of changes + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Refactoring (non-breaking change) +- [ ] Breaking change (fix or feature that would change existing functionality) + +### Checklist + + + + +- [ ] I have read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md) +- [ ] My code follows the code style of the project _(using `npm run lint`)_ +- [ ] My change introduces changes to the documentation +- [ ] I have updated the documentation accordingly +- [ ] I have added tests to cover my changes +- [ ] All new and existing tests passed + +#### Live previews + + + +- + +### Related issues + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/SUPPORT.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/SUPPORT.md new file mode 100644 index 00000000..26b3be42 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/SUPPORT.md @@ -0,0 +1,11 @@ +### Bug reports + +See the [contributing guidelines](CONTRIBUTING.md) for sharing bug reports. + +### How-to + +For general troubleshooting or help getting started: + +- Ask and explore [our GitHub Discussions](https://github.com/twbs/bootstrap/discussions). +- Chat with fellow Bootstrappers in IRC. On the `irc.libera.chat` server, in the `#bootstrap` channel. +- Ask and explore Stack Overflow with the [`bootstrap-5`](https://stackoverflow.com/questions/tagged/bootstrap-5) tag. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/codeql/codeql-config.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/codeql/codeql-config.yml new file mode 100644 index 00000000..95787728 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/codeql/codeql-config.yml @@ -0,0 +1,3 @@ +name: "CodeQL config" +paths-ignore: + - dist diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/dependabot.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/dependabot.yml new file mode 100644 index 00000000..77d36449 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/dependabot.yml @@ -0,0 +1,26 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + day: tuesday + time: "12:00" + timezone: Europe/Athens + - package-ecosystem: npm + directory: "/" + labels: + - dependencies + - v5 + schedule: + interval: weekly + day: tuesday + time: "12:00" + timezone: Europe/Athens + versioning-strategy: increase + rebase-strategy: disabled + groups: + production-dependencies: + dependency-type: "production" + development-dependencies: + dependency-type: "development" diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/release-drafter.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/release-drafter.yml new file mode 100644 index 00000000..0289984b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/release-drafter.yml @@ -0,0 +1,60 @@ +name-template: 'v$NEXT_MAJOR_VERSION' +tag-template: 'v$NEXT_MAJOR_VERSION' +prerelease: true +exclude-labels: + - 'skip-changelog' +categories: + - title: '❗ Breaking Changes' + labels: + - 'breaking-change' + - title: '🚀 Highlights' + labels: + - 'release-highlight' + - title: '🚀 Features' + labels: + - 'new-feature' + - 'feature' + - 'enhancement' + - title: '🐛 Bug fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '⚡ Performance improvements' + labels: + - 'performance' + - title: '🎨 CSS' + labels: + - 'css' + - title: '☕️ JavaScript' + labels: + - 'js' + - title: '📖 Docs' + labels: + - 'docs' + - title: '🛠 Examples' + labels: + - 'examples' + - title: '🌎 Accessibility' + labels: + - 'accessibility' + - title: '🔧 Utility API' + labels: + - 'utility API' + - 'utilities' + - title: '🏭 Tests' + labels: + - 'tests' + - title: '🧰 Misc' + labels: + - 'build' + - 'meta' + - 'chore' + - 'CI' + - title: '📦 Dependencies' + labels: + - 'dependencies' +change-template: '- #$NUMBER: $TITLE' +template: | + ## Changes + $CHANGES diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/browserstack.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/browserstack.yml new file mode 100644 index 00000000..a53c233c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/browserstack.yml @@ -0,0 +1,46 @@ +name: BrowserStack + +on: + push: + branches: + - "**" + - "!dependabot/**" + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + browserstack: + runs-on: ubuntu-latest + if: github.repository == 'twbs/bootstrap' + timeout-minutes: 30 + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "${{ env.NODE }}" + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Run dist + run: npm run dist + + - name: Run BrowserStack tests + run: npm run js-test-cloud + env: + BROWSER_STACK_ACCESS_KEY: "${{ secrets.BROWSER_STACK_ACCESS_KEY }}" + BROWSER_STACK_USERNAME: "${{ secrets.BROWSER_STACK_USERNAME }}" + GITHUB_SHA: "${{ github.sha }}" diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/bundlewatch.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/bundlewatch.yml new file mode 100644 index 00000000..99ba0606 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/bundlewatch.yml @@ -0,0 +1,43 @@ +name: Bundlewatch + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + bundlewatch: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "${{ env.NODE }}" + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Run dist + run: npm run dist + + - name: Run bundlewatch + run: npm run bundlewatch + env: + BUNDLEWATCH_GITHUB_TOKEN: "${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}" + CI_BRANCH_BASE: main diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/calibreapp-image-actions.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/calibreapp-image-actions.yml new file mode 100644 index 00000000..08987b3a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/calibreapp-image-actions.yml @@ -0,0 +1,32 @@ +name: Compress Images + +on: + pull_request: + paths: + - '**.jpg' + - '**.jpeg' + - '**.png' + - '**.webp' + +permissions: + contents: read + +jobs: + build: + # Only run on Pull Requests within the same repository, and not from forks. + if: github.event.pull_request.head.repo.full_name == github.repository + name: calibreapp/image-actions + runs-on: ubuntu-latest + permissions: + # allow calibreapp/image-actions to update PRs + pull-requests: write + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Compress Images + uses: calibreapp/image-actions@1.1.0 + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/codeql.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/codeql.yml new file mode 100644 index 00000000..dd7f6e7e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/codeql.yml @@ -0,0 +1,44 @@ +name: "CodeQL" + +on: + push: + branches: + - main + - v4-dev + - "!dependabot/**" + pull_request: + branches: + - main + - v4-dev + - "!dependabot/**" + schedule: + - cron: "0 2 * * 4" + workflow_dispatch: + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + config-file: ./.github/codeql/codeql-config.yml + languages: "javascript" + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:javascript" diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/cspell.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/cspell.yml new file mode 100644 index 00000000..8708673b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/cspell.yml @@ -0,0 +1,36 @@ +name: cspell + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + +permissions: + contents: read + +jobs: + cspell: + permissions: + # allow streetsidesoftware/cspell-action to fetch files for commits and PRs + contents: read + pull-requests: read + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Run cspell + uses: streetsidesoftware/cspell-action@v6 + with: + config: ".cspell.json" + files: "**/*.{md,mdx}" + inline: error + incremental_files_only: false diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/css.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/css.yml new file mode 100644 index 00000000..52e93e2b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/css.yml @@ -0,0 +1,40 @@ +name: CSS + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + css: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "${{ env.NODE }}" + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Build CSS + run: npm run css + + - name: Run CSS tests + run: npm run css-test diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/docs.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/docs.yml new file mode 100644 index 00000000..08222056 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/docs.yml @@ -0,0 +1,50 @@ +name: Docs + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + docs: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "${{ env.NODE }}" + cache: npm + + - run: java -version + + - name: Install npm dependencies + run: npm ci + + - name: Build docs + run: npm run docs-build + + - name: Validate HTML + run: npm run docs-vnu + + - name: Run linkinator + uses: JustinBeckwith/linkinator-action@v1 + with: + paths: _site + recurse: true + verbosity: error + skip: "^(?!http://localhost)" diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-close-require.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-close-require.yml new file mode 100644 index 00000000..b5000d8b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-close-require.yml @@ -0,0 +1,26 @@ +name: Close Issue Awaiting Reply + +on: + schedule: + - cron: "0 0 * * *" + +permissions: + contents: read + +jobs: + issue-close-require: + permissions: + # allow actions-cool/issues-helper to update issues and PRs + issues: write + pull-requests: write + runs-on: ubuntu-latest + if: github.repository == 'twbs/bootstrap' + steps: + - name: awaiting reply + uses: actions-cool/issues-helper@v3 + with: + actions: "close-issues" + labels: "awaiting-reply" + inactive-day: 14 + body: | + As the issue was labeled with `awaiting-reply`, but there has been no response in 14 days, this issue will be closed. If you have any questions, you can comment/reply. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-labeled.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-labeled.yml new file mode 100644 index 00000000..584879dd --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/issue-labeled.yml @@ -0,0 +1,26 @@ +name: Issue Labeled + +on: + issues: + types: [labeled] + +permissions: + contents: read + +jobs: + issue-labeled: + permissions: + # allow actions-cool/issues-helper to update issues and PRs + issues: write + pull-requests: write + if: github.repository == 'twbs/bootstrap' + runs-on: ubuntu-latest + steps: + - name: awaiting reply + if: github.event.label.name == 'needs-example' + uses: actions-cool/issues-helper@v3 + with: + actions: "create-comment" + token: ${{ secrets.GITHUB_TOKEN }} + body: | + Hello @${{ github.event.issue.user.login }}. Bug reports must include a **live demo** of the issue. Per our [contributing guidelines](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md), please create a reduced test case on [CodePen](https://codepen.io/) or [StackBlitz](https://stackblitz.com/) and report back with your link, Bootstrap version, and specific browser and Operating System details. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/js.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/js.yml new file mode 100644 index 00000000..1b672aa3 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/js.yml @@ -0,0 +1,52 @@ +name: JS Tests + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + run: + permissions: + # allow coverallsapp/github-action to create new checks issues and fetch code + checks: write + contents: read + name: JS Tests + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE }} + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Run dist + run: npm run js + + - name: Run JS tests + run: npm run js-test + + - name: Run Coveralls + uses: coverallsapp/github-action@v2 + if: ${{ !github.event.repository.fork }} + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + path-to-lcov: "./js/coverage/lcov.info" diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/lint.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/lint.yml new file mode 100644 index 00000000..213f9ec6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/lint.yml @@ -0,0 +1,37 @@ +name: Lint + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "${{ env.NODE }}" + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Lint + run: npm run lint diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/node-sass.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/node-sass.yml new file mode 100644 index 00000000..493cc35f --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/node-sass.yml @@ -0,0 +1,49 @@ +name: CSS (node-sass) + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + FORCE_COLOR: 2 + NODE: 20 + +permissions: + contents: read + +jobs: + css: + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "${{ env.NODE }}" + + - name: Build CSS with node-sass + run: | + npx --package node-sass@latest node-sass --version + npx --package node-sass@latest node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/ -o dist-sass/css/ + ls -Al dist-sass/css + + - name: Check built CSS files for Sass variables + shell: bash + run: | + SASS_VARS_FOUND=$(find "dist-sass/css/" -type f -name "*.css" -print0 | xargs -0 --no-run-if-empty grep -F "\$" || true) + if [[ -z "$SASS_VARS_FOUND" ]]; then + echo "All good, no Sass variables found!" + exit 0 + else + echo "Found $(echo "$SASS_VARS_FOUND" | wc -l | bc) Sass variables:" + echo "$SASS_VARS_FOUND" + exit 1 + fi diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/release-notes.yml b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/release-notes.yml new file mode 100644 index 00000000..813956af --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.github/workflows/release-notes.yml @@ -0,0 +1,23 @@ +name: Release notes + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +jobs: + update_release_draft: + permissions: + # allow release-drafter/release-drafter to create GitHub releases and add labels to PRs + contents: write + pull-requests: write + runs-on: ubuntu-latest + if: github.repository == 'twbs/bootstrap' + steps: + - uses: release-drafter/release-drafter@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.prettierignore b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.prettierignore new file mode 100644 index 00000000..32442e87 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.prettierignore @@ -0,0 +1,12 @@ +# Prettier is only used for the website + +site/.astro +site/dist +site/public +site/src/assets +site/src/scss +site/src/pages/**/*.md +site/src/pages/**/*.mdx +site/src/content/**/*.mdx +site/src/layouts/RedirectLayout.astro +site/static diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintignore b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintignore new file mode 100644 index 00000000..b7013de7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintignore @@ -0,0 +1,6 @@ +**/*.min.css +**/dist/ +**/vendor/ +/_site/ +/site/public/ +/js/coverage/ diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintrc.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintrc.json new file mode 100644 index 00000000..589884aa --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/.stylelintrc.json @@ -0,0 +1,60 @@ +{ + "extends": [ + "stylelint-config-twbs-bootstrap" + ], + "reportInvalidScopeDisables": true, + "reportNeedlessDisables": true, + "overrides": [ + { + "files": "**/*.scss", + "rules": { + "declaration-property-value-disallowed-list": { + "border": "none", + "outline": "none" + }, + "function-disallowed-list": [ + "calc", + "lighten", + "darken" + ], + "property-disallowed-list": [ + "border-radius", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius", + "transition" + ], + "scss/dollar-variable-default": [ + true, + { + "ignore": "local" + } + ], + "scss/selector-no-union-class-name": true + } + }, + { + "files": "scss/**/*.{test,spec}.scss", + "rules": { + "scss/dollar-variable-default": null, + "declaration-no-important": null + } + }, + { + "files": "site/**/*.scss", + "rules": { + "scss/dollar-variable-default": null + } + }, + { + "files": "site/**/examples/**/*.css", + "rules": { + "comment-empty-line-before": null, + "property-no-vendor-prefix": null, + "selector-no-qualifying-type": null, + "value-no-vendor-prefix": null + } + } + ] +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/CODE_OF_CONDUCT.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..75629831 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of + any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others’ private information, such as a physical or email address, + without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +mdo@getbootstrap.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/Gruntfile.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/Gruntfile.js deleted file mode 100644 index 4c021cef..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/Gruntfile.js +++ /dev/null @@ -1,531 +0,0 @@ -/*! - * Bootstrap's Gruntfile - * http://getbootstrap.com - * Copyright 2013-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -module.exports = function (grunt) { - 'use strict'; - - // Force use of Unix newlines - grunt.util.linefeed = '\n'; - - RegExp.quote = function (string) { - return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); - }; - - var fs = require('fs'); - var path = require('path'); - var npmShrinkwrap = require('npm-shrinkwrap'); - var generateGlyphiconsData = require('./grunt/bs-glyphicons-data-generator.js'); - var BsLessdocParser = require('./grunt/bs-lessdoc-parser.js'); - var getLessVarsData = function () { - var filePath = path.join(__dirname, 'less/variables.less'); - var fileContent = fs.readFileSync(filePath, { encoding: 'utf8' }); - var parser = new BsLessdocParser(fileContent); - return { sections: parser.parseFile() }; - }; - var generateRawFiles = require('./grunt/bs-raw-files-generator.js'); - var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js'); - var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' }); - - Object.keys(configBridge.paths).forEach(function (key) { - configBridge.paths[key].forEach(function (val, i, arr) { - arr[i] = path.join('./docs/assets', val); - }); - }); - - // Project configuration. - grunt.initConfig({ - - // Metadata. - pkg: grunt.file.readJSON('package.json'), - banner: '/*!\n' + - ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' + - ' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + - ' * Licensed under the <%= pkg.license %> license\n' + - ' */\n', - jqueryCheck: configBridge.config.jqueryCheck.join('\n'), - jqueryVersionCheck: configBridge.config.jqueryVersionCheck.join('\n'), - - // Task configuration. - clean: { - dist: 'dist', - docs: 'docs/dist' - }, - - jshint: { - options: { - jshintrc: 'js/.jshintrc' - }, - grunt: { - options: { - jshintrc: 'grunt/.jshintrc' - }, - src: ['Gruntfile.js', 'package.js', 'grunt/*.js'] - }, - core: { - src: 'js/*.js' - }, - test: { - options: { - jshintrc: 'js/tests/unit/.jshintrc' - }, - src: 'js/tests/unit/*.js' - }, - assets: { - src: ['docs/assets/js/src/*.js', 'docs/assets/js/*.js', '!docs/assets/js/*.min.js'] - } - }, - - jscs: { - options: { - config: 'js/.jscsrc' - }, - grunt: { - src: '<%= jshint.grunt.src %>' - }, - core: { - src: '<%= jshint.core.src %>' - }, - test: { - src: '<%= jshint.test.src %>' - }, - assets: { - options: { - requireCamelCaseOrUpperCaseIdentifiers: null - }, - src: '<%= jshint.assets.src %>' - } - }, - - concat: { - options: { - banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>', - stripBanners: false - }, - bootstrap: { - src: [ - 'js/transition.js', - 'js/alert.js', - 'js/button.js', - 'js/carousel.js', - 'js/collapse.js', - 'js/dropdown.js', - 'js/modal.js', - 'js/tooltip.js', - 'js/popover.js', - 'js/scrollspy.js', - 'js/tab.js', - 'js/affix.js' - ], - dest: 'dist/js/<%= pkg.name %>.js' - } - }, - - uglify: { - options: { - compress: { - warnings: false - }, - mangle: true, - preserveComments: 'some' - }, - core: { - src: '<%= concat.bootstrap.dest %>', - dest: 'dist/js/<%= pkg.name %>.min.js' - }, - customize: { - src: configBridge.paths.customizerJs, - dest: 'docs/assets/js/customize.min.js' - }, - docsJs: { - src: configBridge.paths.docsJs, - dest: 'docs/assets/js/docs.min.js' - } - }, - - qunit: { - options: { - inject: 'js/tests/unit/phantom.js' - }, - files: 'js/tests/index.html' - }, - - less: { - compileCore: { - options: { - strictMath: true, - sourceMap: true, - outputSourceFiles: true, - sourceMapURL: '<%= pkg.name %>.css.map', - sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map' - }, - src: 'less/bootstrap.less', - dest: 'dist/css/<%= pkg.name %>.css' - }, - compileTheme: { - options: { - strictMath: true, - sourceMap: true, - outputSourceFiles: true, - sourceMapURL: '<%= pkg.name %>-theme.css.map', - sourceMapFilename: 'dist/css/<%= pkg.name %>-theme.css.map' - }, - src: 'less/theme.less', - dest: 'dist/css/<%= pkg.name %>-theme.css' - } - }, - - autoprefixer: { - options: { - browsers: configBridge.config.autoprefixerBrowsers - }, - core: { - options: { - map: true - }, - src: 'dist/css/<%= pkg.name %>.css' - }, - theme: { - options: { - map: true - }, - src: 'dist/css/<%= pkg.name %>-theme.css' - }, - docs: { - src: ['docs/assets/css/src/docs.css'] - }, - examples: { - expand: true, - cwd: 'docs/examples/', - src: ['**/*.css'], - dest: 'docs/examples/' - } - }, - - csslint: { - options: { - csslintrc: 'less/.csslintrc' - }, - dist: [ - 'dist/css/bootstrap.css', - 'dist/css/bootstrap-theme.css' - ], - examples: [ - 'docs/examples/**/*.css' - ], - docs: { - options: { - ids: false, - 'overqualified-elements': false - }, - src: 'docs/assets/css/src/docs.css' - } - }, - - cssmin: { - options: { - // TODO: disable `zeroUnits` optimization once clean-css 3.2 is released - // and then simplify the fix for https://github.com/twbs/bootstrap/issues/14837 accordingly - compatibility: 'ie8', - keepSpecialComments: '*', - advanced: false - }, - minifyCore: { - src: 'dist/css/<%= pkg.name %>.css', - dest: 'dist/css/<%= pkg.name %>.min.css' - }, - minifyTheme: { - src: 'dist/css/<%= pkg.name %>-theme.css', - dest: 'dist/css/<%= pkg.name %>-theme.min.css' - }, - docs: { - src: [ - 'docs/assets/css/src/pygments-manni.css', - 'docs/assets/css/src/docs.css' - ], - dest: 'docs/assets/css/docs.min.css' - } - }, - - csscomb: { - options: { - config: 'less/.csscomb.json' - }, - dist: { - expand: true, - cwd: 'dist/css/', - src: ['*.css', '!*.min.css'], - dest: 'dist/css/' - }, - examples: { - expand: true, - cwd: 'docs/examples/', - src: '**/*.css', - dest: 'docs/examples/' - }, - docs: { - src: 'docs/assets/css/src/docs.css', - dest: 'docs/assets/css/src/docs.css' - } - }, - - copy: { - fonts: { - expand: true, - src: 'fonts/*', - dest: 'dist/' - }, - docs: { - expand: true, - cwd: 'dist/', - src: [ - '**/*' - ], - dest: 'docs/dist/' - } - }, - - connect: { - server: { - options: { - port: 3000, - base: '.' - } - } - }, - - jekyll: { - options: { - config: '_config.yml' - }, - docs: {}, - github: { - options: { - raw: 'github: true' - } - } - }, - - htmlmin: { - dist: { - options: { - collapseWhitespace: true, - conservativeCollapse: true, - minifyCSS: true, - minifyJS: true, - removeAttributeQuotes: true, - removeComments: true - }, - expand: true, - cwd: '_gh_pages', - dest: '_gh_pages', - src: [ - '**/*.html', - '!examples/**/*.html' - ] - } - }, - - jade: { - options: { - pretty: true, - data: getLessVarsData - }, - customizerVars: { - src: 'docs/_jade/customizer-variables.jade', - dest: 'docs/_includes/customizer-variables.html' - }, - customizerNav: { - src: 'docs/_jade/customizer-nav.jade', - dest: 'docs/_includes/nav/customize.html' - } - }, - - htmllint: { - options: { - ignore: [ - 'Attribute "autocomplete" not allowed on element "button" at this point.', - 'Attribute "autocomplete" not allowed on element "input" at this point.', - 'Element "img" is missing required attribute "src".' - ] - }, - src: '_gh_pages/**/*.html' - }, - - watch: { - src: { - files: '<%= jshint.core.src %>', - tasks: ['jshint:core', 'qunit', 'concat'] - }, - test: { - files: '<%= jshint.test.src %>', - tasks: ['jshint:test', 'qunit'] - }, - less: { - files: 'less/**/*.less', - tasks: 'less' - } - }, - - sed: { - versionNumber: { - pattern: (function () { - var old = grunt.option('oldver'); - return old ? RegExp.quote(old) : old; - })(), - replacement: grunt.option('newver'), - exclude: [ - 'dist/fonts', - 'docs/assets', - 'fonts', - 'js/tests/vendor', - 'node_modules', - 'test-infra' - ], - recursive: true - } - }, - - 'saucelabs-qunit': { - all: { - options: { - build: process.env.TRAVIS_JOB_ID, - throttled: 10, - maxRetries: 3, - maxPollRetries: 4, - urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'], - browsers: grunt.file.readYAML('grunt/sauce_browsers.yml') - } - } - }, - - exec: { - npmUpdate: { - command: 'npm update' - } - }, - - compress: { - main: { - options: { - archive: 'bootstrap-<%= pkg.version %>-dist.zip', - mode: 'zip', - level: 9, - pretty: true - }, - files: [ - { - expand: true, - cwd: 'dist/', - src: ['**'], - dest: 'bootstrap-<%= pkg.version %>-dist' - } - ] - } - } - - }); - - - // These plugins provide necessary tasks. - require('load-grunt-tasks')(grunt, { scope: 'devDependencies' }); - require('time-grunt')(grunt); - - // Docs HTML validation task - grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint']); - - var runSubset = function (subset) { - return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset; - }; - var isUndefOrNonZero = function (val) { - return val === undefined || val !== '0'; - }; - - // Test task. - var testSubtasks = []; - // Skip core tests if running a different subset of the test suite - if (runSubset('core') && - // Skip core tests if this is a Savage build - process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { - testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'csslint:dist', 'test-js', 'docs']); - } - // Skip HTML validation if running a different subset of the test suite - if (runSubset('validate-html') && - // Skip HTML5 validator on Travis when [skip validator] is in the commit message - isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) { - testSubtasks.push('validate-html'); - } - // Only run Sauce Labs tests if there's a Sauce access key - if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' && - // Skip Sauce if running a different subset of the test suite - runSubset('sauce-js-unit') && - // Skip Sauce on Travis when [skip sauce] is in the commit message - isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) { - testSubtasks.push('connect'); - testSubtasks.push('saucelabs-qunit'); - } - grunt.registerTask('test', testSubtasks); - grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']); - - // JS distribution task. - grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']); - - // CSS distribution task. - grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme']); - grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'csscomb:dist', 'cssmin:minifyCore', 'cssmin:minifyTheme']); - - // Full distribution task. - grunt.registerTask('dist', ['clean:dist', 'dist-css', 'copy:fonts', 'dist-js']); - - // Default task. - grunt.registerTask('default', ['clean:dist', 'copy:fonts', 'test']); - - // Version numbering task. - // grunt change-version-number --oldver=A.B.C --newver=X.Y.Z - // This can be overzealous, so its changes should always be manually reviewed! - grunt.registerTask('change-version-number', 'sed'); - - grunt.registerTask('build-glyphicons-data', function () { generateGlyphiconsData.call(this, grunt); }); - - // task for building customizer - grunt.registerTask('build-customizer', ['build-customizer-html', 'build-raw-files']); - grunt.registerTask('build-customizer-html', 'jade'); - grunt.registerTask('build-raw-files', 'Add scripts/less files to customizer.', function () { - var banner = grunt.template.process('<%= banner %>'); - generateRawFiles(grunt, banner); - }); - - grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function () { - var srcFiles = grunt.config.get('concat.bootstrap.src'); - var destFilepath = 'dist/js/npm.js'; - generateCommonJSModule(grunt, srcFiles, destFilepath); - }); - - // Docs task. - grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']); - grunt.registerTask('lint-docs-css', ['csslint:docs', 'csslint:examples']); - grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']); - grunt.registerTask('lint-docs-js', ['jshint:assets', 'jscs:assets']); - grunt.registerTask('docs', ['docs-css', 'lint-docs-css', 'docs-js', 'lint-docs-js', 'clean:docs', 'copy:docs', 'build-glyphicons-data', 'build-customizer']); - - grunt.registerTask('prep-release', ['dist', 'docs', 'jekyll:github', 'htmlmin', 'compress']); - - // Task for updating the cached npm packages used by the Travis build (which are controlled by test-infra/npm-shrinkwrap.json). - // This task should be run and the updated file should be committed whenever Bootstrap's dependencies change. - grunt.registerTask('update-shrinkwrap', ['exec:npmUpdate', '_update-shrinkwrap']); - grunt.registerTask('_update-shrinkwrap', function () { - var done = this.async(); - npmShrinkwrap({ dev: true, dirname: __dirname }, function (err) { - if (err) { - grunt.fail.warn(err); - } - var dest = 'test-infra/npm-shrinkwrap.json'; - fs.renameSync('npm-shrinkwrap.json', dest); - grunt.log.writeln('File ' + dest.cyan + ' updated.'); - done(); - }); - }); -}; diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/LICENSE b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/LICENSE index f4c52d6a..fa7c00bc 100644 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/LICENSE +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2011-2015 Twitter, Inc +Copyright (c) 2011-2025 The Bootstrap Authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/README.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/README.md index 34c8b5a5..b86bd5f8 100644 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/README.md +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/README.md @@ -1,137 +1,247 @@ -# [Bootstrap](http://getbootstrap.com) -[![Slack](https://bootstrap-slack.herokuapp.com/badge.svg)](https://bootstrap-slack.herokuapp.com) -![Bower version](https://img.shields.io/bower/v/bootstrap.svg) -[![npm version](https://img.shields.io/npm/v/bootstrap.svg)](https://www.npmjs.com/package/bootstrap) -[![Build Status](https://img.shields.io/travis/twbs/bootstrap/master.svg)](https://travis-ci.org/twbs/bootstrap) -[![devDependency Status](https://img.shields.io/david/dev/twbs/bootstrap.svg)](https://david-dm.org/twbs/bootstrap#info=devDependencies) -[![Selenium Test Status](https://saucelabs.com/browser-matrix/bootstrap.svg)](https://saucelabs.com/u/bootstrap) +

    + + Bootstrap logo + +

    -Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created by [Mark Otto](https://twitter.com/mdo) and [Jacob Thornton](https://twitter.com/fat), and maintained by the [core team](https://github.com/orgs/twbs/people) with the massive support and involvement of the community. +

    Bootstrap

    + +

    + Sleek, intuitive, and powerful front-end framework for faster and easier web development. +
    + Explore Bootstrap docs » +
    +
    + Report bug + · + Request feature + · + Themes + · + Blog +

    + + +## Bootstrap 5 + +Our default branch is for development of our Bootstrap 5 release. Head to the [`v4-dev` branch](https://github.com/twbs/bootstrap/tree/v4-dev) to view the readme, documentation, and source code for Bootstrap 4. -To get started, check out ! ## Table of contents - [Quick start](#quick-start) +- [Status](#status) +- [What’s included](#whats-included) - [Bugs and feature requests](#bugs-and-feature-requests) - [Documentation](#documentation) - [Contributing](#contributing) - [Community](#community) - [Versioning](#versioning) - [Creators](#creators) +- [Thanks](#thanks) - [Copyright and license](#copyright-and-license) + ## Quick start Several quick start options are available: -- [Download the latest release](https://github.com/twbs/bootstrap/archive/v3.3.5.zip). -- Clone the repo: `git clone https://github.com/twbs/bootstrap.git`. -- Install with [Bower](http://bower.io): `bower install bootstrap`. -- Install with [npm](https://www.npmjs.com): `npm install bootstrap`. -- Install with [Meteor](https://www.meteor.com): `meteor add twbs:bootstrap`. -- Install with [Composer](https://getcomposer.org): `composer require twbs/bootstrap`. +- [Download the latest release](https://github.com/twbs/bootstrap/archive/v5.3.6.zip) +- Clone the repo: `git clone https://github.com/twbs/bootstrap.git` +- Install with [npm](https://www.npmjs.com/): `npm install bootstrap@v5.3.6` +- Install with [yarn](https://yarnpkg.com/): `yarn add bootstrap@v5.3.6` +- Install with [Bun](https://bun.sh/): `bun add bootstrap@v5.3.6` +- Install with [Composer](https://getcomposer.org/): `composer require twbs/bootstrap:5.3.6` +- Install with [NuGet](https://www.nuget.org/): CSS: `Install-Package bootstrap` Sass: `Install-Package bootstrap.sass` -Read the [Getting started page](http://getbootstrap.com/getting-started/) for information on the framework contents, templates and examples, and more. +Read the [Getting started page](https://getbootstrap.com/docs/5.3/getting-started/introduction/) for information on the framework contents, templates, examples, and more. -### What's included -Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this: +## Status -``` -bootstrap/ -├── css/ -│ ├── bootstrap.css -│ ├── bootstrap.css.map -│ ├── bootstrap.min.css -│ ├── bootstrap-theme.css -│ ├── bootstrap-theme.css.map -│ └── bootstrap-theme.min.css -├── js/ -│ ├── bootstrap.js -│ └── bootstrap.min.js -└── fonts/ - ├── glyphicons-halflings-regular.eot - ├── glyphicons-halflings-regular.svg - ├── glyphicons-halflings-regular.ttf - ├── glyphicons-halflings-regular.woff - └── glyphicons-halflings-regular.woff2 -``` +[![Build Status](https://img.shields.io/github/actions/workflow/status/twbs/bootstrap/js.yml?branch=main&label=JS%20Tests&logo=github)](https://github.com/twbs/bootstrap/actions/workflows/js.yml?query=workflow%3AJS+branch%3Amain) +[![npm version](https://img.shields.io/npm/v/bootstrap?logo=npm&logoColor=fff)](https://www.npmjs.com/package/bootstrap) +[![Gem version](https://img.shields.io/gem/v/bootstrap?logo=rubygems&logoColor=fff)](https://rubygems.org/gems/bootstrap) +[![Meteor Atmosphere](https://img.shields.io/badge/meteor-twbs%3Abootstrap-blue?logo=meteor&logoColor=fff)](https://atmospherejs.com/twbs/bootstrap) +[![Packagist Prerelease](https://img.shields.io/packagist/vpre/twbs/bootstrap?logo=packagist&logoColor=fff)](https://packagist.org/packages/twbs/bootstrap) +[![NuGet](https://img.shields.io/nuget/vpre/bootstrap?logo=nuget&logoColor=fff)](https://www.nuget.org/packages/bootstrap/absoluteLatest) +[![Coverage Status](https://img.shields.io/coveralls/github/twbs/bootstrap/main?logo=coveralls&logoColor=fff)](https://coveralls.io/github/twbs/bootstrap?branch=main) +[![CSS gzip size](https://img.badgesize.io/twbs/bootstrap/main/dist/css/bootstrap.min.css?compression=gzip&label=CSS%20gzip%20size)](https://github.com/twbs/bootstrap/blob/main/dist/css/bootstrap.min.css) +[![CSS Brotli size](https://img.badgesize.io/twbs/bootstrap/main/dist/css/bootstrap.min.css?compression=brotli&label=CSS%20Brotli%20size)](https://github.com/twbs/bootstrap/blob/main/dist/css/bootstrap.min.css) +[![JS gzip size](https://img.badgesize.io/twbs/bootstrap/main/dist/js/bootstrap.min.js?compression=gzip&label=JS%20gzip%20size)](https://github.com/twbs/bootstrap/blob/main/dist/js/bootstrap.min.js) +[![JS Brotli size](https://img.badgesize.io/twbs/bootstrap/main/dist/js/bootstrap.min.js?compression=brotli&label=JS%20Brotli%20size)](https://github.com/twbs/bootstrap/blob/main/dist/js/bootstrap.min.js) +[![Backers on Open Collective](https://img.shields.io/opencollective/backers/bootstrap?logo=opencollective&logoColor=fff)](#backers) +[![Sponsors on Open Collective](https://img.shields.io/opencollective/sponsors/bootstrap?logo=opencollective&logoColor=fff)](#sponsors) -We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). CSS [source maps](https://developer.chrome.com/devtools/docs/css-preprocessors) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Fonts from Glyphicons are included, as is the optional Bootstrap theme. +## What’s included + +Within the download you’ll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. + +
    + Download contents + + ```text + bootstrap/ + ├── css/ + │ ├── bootstrap-grid.css + │ ├── bootstrap-grid.css.map + │ ├── bootstrap-grid.min.css + │ ├── bootstrap-grid.min.css.map + │ ├── bootstrap-grid.rtl.css + │ ├── bootstrap-grid.rtl.css.map + │ ├── bootstrap-grid.rtl.min.css + │ ├── bootstrap-grid.rtl.min.css.map + │ ├── bootstrap-reboot.css + │ ├── bootstrap-reboot.css.map + │ ├── bootstrap-reboot.min.css + │ ├── bootstrap-reboot.min.css.map + │ ├── bootstrap-reboot.rtl.css + │ ├── bootstrap-reboot.rtl.css.map + │ ├── bootstrap-reboot.rtl.min.css + │ ├── bootstrap-reboot.rtl.min.css.map + │ ├── bootstrap-utilities.css + │ ├── bootstrap-utilities.css.map + │ ├── bootstrap-utilities.min.css + │ ├── bootstrap-utilities.min.css.map + │ ├── bootstrap-utilities.rtl.css + │ ├── bootstrap-utilities.rtl.css.map + │ ├── bootstrap-utilities.rtl.min.css + │ ├── bootstrap-utilities.rtl.min.css.map + │ ├── bootstrap.css + │ ├── bootstrap.css.map + │ ├── bootstrap.min.css + │ ├── bootstrap.min.css.map + │ ├── bootstrap.rtl.css + │ ├── bootstrap.rtl.css.map + │ ├── bootstrap.rtl.min.css + │ └── bootstrap.rtl.min.css.map + └── js/ + ├── bootstrap.bundle.js + ├── bootstrap.bundle.js.map + ├── bootstrap.bundle.min.js + ├── bootstrap.bundle.min.js.map + ├── bootstrap.esm.js + ├── bootstrap.esm.js.map + ├── bootstrap.esm.min.js + ├── bootstrap.esm.min.js.map + ├── bootstrap.js + ├── bootstrap.js.map + ├── bootstrap.min.js + └── bootstrap.min.js.map + ``` +
    + +We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://web.dev/articles/source-maps) (`bootstrap.*.map`) are available for use with certain browsers’ developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/docs/v2/). ## Bugs and feature requests -Have a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new). +Have a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new/choose). ## Documentation -Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at . The docs may also be run locally. +Bootstrap’s documentation, included in this repo in the root directory, is built with [Astro](https://astro.build/) and publicly hosted on GitHub Pages at . The docs may also be run locally. + +Documentation search is powered by [Algolia's DocSearch](https://docsearch.algolia.com/). ### Running documentation locally -1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v2.5.x). - - **Windows users:** Read [this unofficial guide](http://jekyll-windows.juthilo.com/) to get Jekyll up and running without problems. -2. Install the Ruby-based syntax highlighter, [Rouge](https://github.com/jneen/rouge), with `gem install rouge`. -3. From the root `/bootstrap` directory, run `jekyll serve` in the command line. -4. Open in your browser, and voilà. +1. Run `npm install` to install the Node.js dependencies, including Astro (the site builder). +2. Run `npm run test` (or a specific npm script) to rebuild distributed CSS and JavaScript files, as well as our docs assets. +3. From the root `/bootstrap` directory, run `npm run docs-serve` in the command line. +4. Open `http://localhost:9001/` in your browser, and voilà. -Learn more about using Jekyll by reading its [documentation](http://jekyllrb.com/docs/home/). +Learn more about using Astro by reading its [documentation](https://docs.astro.build/en/getting-started/). ### Documentation for previous releases -Documentation for v2.3.2 has been made available for the time being at while folks transition to Bootstrap 3. +You can find all our previous releases docs on . [Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download. - ## Contributing -Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. +Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/main/.github/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. -Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/master/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo). - -Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/master/.editorconfig) for easy use in common text editors. Read more and download plugins at . +Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/main/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo). +Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/main/.editorconfig) for easy use in common text editors. Read more and download plugins at . ## Community -Get updates on Bootstrap's development and chat with the project maintainers and community members. +Get updates on Bootstrap’s development and chat with the project maintainers and community members. -- Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap). -- Read and subscribe to [The Official Bootstrap Blog](http://blog.getbootstrap.com). -- Join [the official Slack room](https://bootstrap-slack.herokuapp.com). -- Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##bootstrap` channel. -- Implementation help may be found at Stack Overflow (tagged [`twitter-bootstrap-3`](https://stackoverflow.com/questions/tagged/twitter-bootstrap-3)). +- Follow [@getbootstrap on X](https://x.com/getbootstrap). +- Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com/). +- Ask questions and explore [our GitHub Discussions](https://github.com/twbs/bootstrap/discussions). +- Discuss, ask questions, and more on [the community Discord](https://discord.gg/bZUvakRU3M) or [Bootstrap subreddit](https://www.reddit.com/r/bootstrap/). +- Chat with fellow Bootstrappers in IRC. On the `irc.libera.chat` server, in the `#bootstrap` channel. +- Implementation help may be found at Stack Overflow (tagged [`bootstrap-5`](https://stackoverflow.com/questions/tagged/bootstrap-5)). - Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability. - ## Versioning -For transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](http://semver.org/). Sometimes we screw up, but we'll adhere to those rules whenever possible. +For transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](https://semver.org/). Sometimes we screw up, but we adhere to those rules whenever possible. +See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com/) contain summaries of the most noteworthy changes made in each release. ## Creators **Mark Otto** -- +- - **Jacob Thornton** -- +- - +## Thanks + + + BrowserStack + + +Thanks to [BrowserStack](https://www.browserstack.com/) for providing the infrastructure that allows us to test in real browsers! + + + Netlify + + +Thanks to [Netlify](https://www.netlify.com/) for providing us with Deploy Previews! + + +## Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/bootstrap#sponsor)] + +[![OC sponsor 0](https://opencollective.com/bootstrap/sponsor/0/avatar.svg)](https://opencollective.com/bootstrap/sponsor/0/website) +[![OC sponsor 1](https://opencollective.com/bootstrap/sponsor/1/avatar.svg)](https://opencollective.com/bootstrap/sponsor/1/website) +[![OC sponsor 2](https://opencollective.com/bootstrap/sponsor/2/avatar.svg)](https://opencollective.com/bootstrap/sponsor/2/website) +[![OC sponsor 3](https://opencollective.com/bootstrap/sponsor/3/avatar.svg)](https://opencollective.com/bootstrap/sponsor/3/website) +[![OC sponsor 4](https://opencollective.com/bootstrap/sponsor/4/avatar.svg)](https://opencollective.com/bootstrap/sponsor/4/website) +[![OC sponsor 5](https://opencollective.com/bootstrap/sponsor/5/avatar.svg)](https://opencollective.com/bootstrap/sponsor/5/website) +[![OC sponsor 6](https://opencollective.com/bootstrap/sponsor/6/avatar.svg)](https://opencollective.com/bootstrap/sponsor/6/website) +[![OC sponsor 7](https://opencollective.com/bootstrap/sponsor/7/avatar.svg)](https://opencollective.com/bootstrap/sponsor/7/website) +[![OC sponsor 8](https://opencollective.com/bootstrap/sponsor/8/avatar.svg)](https://opencollective.com/bootstrap/sponsor/8/website) +[![OC sponsor 9](https://opencollective.com/bootstrap/sponsor/9/avatar.svg)](https://opencollective.com/bootstrap/sponsor/9/website) + + +## Backers + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bootstrap#backer)] + +[![Backers](https://opencollective.com/bootstrap/backers.svg?width=890)](https://opencollective.com/bootstrap#backers) + ## Copyright and license -Code and documentation copyright 2011-2015 Twitter, Inc. Code released under [the MIT license](https://github.com/twbs/bootstrap/blob/master/LICENSE). Docs released under [Creative Commons](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE). +Code and documentation copyright 2011-2025 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors). Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/). diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/SECURITY.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/SECURITY.md new file mode 100644 index 00000000..e79dcd8d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/SECURITY.md @@ -0,0 +1,7 @@ +# Reporting Security Issues + +The Bootstrap team and community take security issues in Bootstrap seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +To report a security issue, email [security@getbootstrap.com](mailto:security@getbootstrap.com) and include the word "SECURITY" in the subject line. + +We'll endeavor to respond quickly, and will keep you updated throughout the process. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/bower.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/bower.json deleted file mode 100644 index 686bcf1a..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/bower.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "bootstrap", - "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", - "keywords": [ - "css", - "js", - "less", - "mobile-first", - "responsive", - "front-end", - "framework", - "web" - ], - "homepage": "http://getbootstrap.com", - "license": "MIT", - "moduleType": "globals", - "main": [ - "less/bootstrap.less", - "dist/js/bootstrap.js" - ], - "ignore": [ - "/.*", - "_config.yml", - "CNAME", - "composer.json", - "CONTRIBUTING.md", - "docs", - "js/tests", - "test-infra" - ], - "dependencies": { - "jquery": ">= 1.9.1" - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/banner.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/banner.mjs new file mode 100644 index 00000000..3fea93c8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/banner.mjs @@ -0,0 +1,20 @@ +import fs from 'node:fs/promises' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +const pkgJson = path.join(__dirname, '../package.json') +const pkg = JSON.parse(await fs.readFile(pkgJson, 'utf8')) + +const year = new Date().getFullYear() + +function getBanner(pluginFilename) { + return `/*! + * Bootstrap${pluginFilename ? ` ${pluginFilename}` : ''} v${pkg.version} (${pkg.homepage}) + * Copyright 2011-${year} ${pkg.author} + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */` +} + +export default getBanner diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/build-plugins.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/build-plugins.mjs new file mode 100644 index 00000000..f56cd213 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/build-plugins.mjs @@ -0,0 +1,108 @@ +#!/usr/bin/env node + +/*! + * Script to build our plugins to use them separately. + * Copyright 2020-2025 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ + +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { babel } from '@rollup/plugin-babel' +import { globby } from 'globby' +import { rollup } from 'rollup' +import banner from './banner.mjs' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +const sourcePath = path.resolve(__dirname, '../js/src/').replace(/\\/g, '/') +const jsFiles = await globby(`${sourcePath}/**/*.js`) + +// Array which holds the resolved plugins +const resolvedPlugins = [] + +// Trims the "js" extension and uppercases => first letter, hyphens, backslashes & slashes +const filenameToEntity = filename => filename.replace('.js', '') + .replace(/(?:^|-|\/|\\)[a-z]/g, str => str.slice(-1).toUpperCase()) + +for (const file of jsFiles) { + resolvedPlugins.push({ + src: file, + dist: file.replace('src', 'dist'), + fileName: path.basename(file), + className: filenameToEntity(path.basename(file)) + // safeClassName: filenameToEntity(path.relative(sourcePath, file)) + }) +} + +const build = async plugin => { + /** + * @type {import('rollup').GlobalsOption} + */ + const globals = {} + + const bundle = await rollup({ + input: plugin.src, + plugins: [ + babel({ + // Only transpile our source code + exclude: 'node_modules/**', + // Include the helpers in each file, at most one copy of each + babelHelpers: 'bundled' + }) + ], + external(source) { + // Pattern to identify local files + const pattern = /^(\.{1,2})\// + + // It's not a local file, e.g a Node.js package + if (!pattern.test(source)) { + globals[source] = source + return true + } + + const usedPlugin = resolvedPlugins.find(plugin => { + return plugin.src.includes(source.replace(pattern, '')) + }) + + if (!usedPlugin) { + throw new Error(`Source ${source} is not mapped!`) + } + + // We can change `Index` with `UtilIndex` etc if we use + // `safeClassName` instead of `className` everywhere + globals[path.normalize(usedPlugin.src)] = usedPlugin.className + return true + } + }) + + await bundle.write({ + banner: banner(plugin.fileName), + format: 'umd', + name: plugin.className, + sourcemap: true, + globals, + generatedCode: 'es2015', + file: plugin.dist + }) + + console.log(`Built ${plugin.className}`) +} + +(async () => { + try { + const basename = path.basename(__filename) + const timeLabel = `[${basename}] finished` + + console.log('Building individual plugins...') + console.time(timeLabel) + + await Promise.all(Object.values(resolvedPlugins).map(plugin => build(plugin))) + + console.timeEnd(timeLabel) + } catch (error) { + console.error(error) + process.exit(1) + } +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/change-version.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/change-version.mjs new file mode 100644 index 00000000..1400274c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/change-version.mjs @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +/*! + * Script to update version number references in the project. + * Copyright 2017-2025 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ + +import { execFile } from 'node:child_process' +import fs from 'node:fs/promises' +import process from 'node:process' + +const VERBOSE = process.argv.includes('--verbose') +const DRY_RUN = process.argv.includes('--dry') || process.argv.includes('--dry-run') + +// These are the files we only care about replacing the version +const FILES = [ + 'README.md', + 'config.yml', + 'js/src/base-component.js', + 'package.js', + 'scss/mixins/_banner.scss', + 'site/data/docs-versions.yml' +] + +// Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37 +function regExpQuote(string) { + return string.replace(/[$()*+-.?[\\\]^{|}]/g, '\\$&') +} + +function regExpQuoteReplacement(string) { + return string.replace(/\$/g, '$$') +} + +async function replaceRecursively(file, oldVersion, newVersion) { + const originalString = await fs.readFile(file, 'utf8') + const newString = originalString + .replace( + new RegExp(regExpQuote(oldVersion), 'g'), + regExpQuoteReplacement(newVersion) + ) + // Also replace the version used by the rubygem, + // which is using periods (`.`) instead of hyphens (`-`) + .replace( + new RegExp(regExpQuote(oldVersion.replace(/-/g, '.')), 'g'), + regExpQuoteReplacement(newVersion.replace(/-/g, '.')) + ) + + // No need to move any further if the strings are identical + if (originalString === newString) { + return + } + + if (VERBOSE) { + console.log(`Found ${oldVersion} in ${file}`) + } + + if (DRY_RUN) { + return + } + + await fs.writeFile(file, newString, 'utf8') +} + +function bumpNpmVersion(newVersion) { + if (DRY_RUN) { + return + } + + execFile('npm', ['version', newVersion, '--no-git-tag'], { shell: true }, error => { + if (error) { + console.error(error) + process.exit(1) + } + }) +} + +function showUsage(args) { + console.error('USAGE: change-version old_version new_version [--verbose] [--dry[-run]]') + console.error('Got arguments:', args) + process.exit(1) +} + +async function main(args) { + let [oldVersion, newVersion] = args + + if (!oldVersion || !newVersion) { + showUsage(args) + } + + // Strip any leading `v` from arguments because + // otherwise we will end up with duplicate `v`s + [oldVersion, newVersion] = [oldVersion, newVersion].map(arg => { + return arg.startsWith('v') ? arg.slice(1) : arg + }) + + if (oldVersion === newVersion) { + showUsage(args) + } + + bumpNpmVersion(newVersion) + + try { + await Promise.all( + FILES.map(file => replaceRecursively(file, oldVersion, newVersion)) + ) + } catch (error) { + console.error(error) + process.exit(1) + } +} + +main(process.argv.slice(2)) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/docs-prep.sh b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/docs-prep.sh new file mode 100755 index 00000000..2586ad34 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/docs-prep.sh @@ -0,0 +1,169 @@ +#!/bin/bash + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Default branch suffix +BRANCH_SUFFIX="release" + +# Check if a custom version parameter was provided +if [ $# -eq 1 ]; then + BRANCH_SUFFIX="$1" +fi + +# Branch name to create +NEW_BRANCH="gh-pages-${BRANCH_SUFFIX}" + +# Function to print colored messages +print_success() { + echo -e "${GREEN}✓ $1${NC}" +} + +print_error() { + echo -e "${RED}✗ $1${NC}" + exit 1 +} + +print_info() { + echo -e "${BLUE}ℹ $1${NC}" +} + +print_warning() { + echo -e "${YELLOW}⚠ $1${NC}" +} + +# Function to execute command with error handling +execute() { + print_info "Running: $1" + eval $1 + if [ $? -ne 0 ]; then + print_error "Failed to execute: $1" + else + print_success "Successfully executed: $1" + fi +} + +# Check if /tmp/_site directory exists from a previous run +if [ -d "/tmp/_site" ]; then + print_warning "Found existing /tmp/_site directory. Removing it…" + rm -rf /tmp/_site +fi + +# Main process +print_info "Starting documentation deployment process…" + +# Step 1: Build documentation +print_info "Building documentation with npm run docs…" +npm run docs +if [ $? -ne 0 ]; then + print_error "Documentation build failed!" +fi +print_success "Documentation built successfully" + +# Step 2: Move _site to /tmp/ +print_info "Moving _site to temporary location…" +execute "mv _site /tmp/" + +# Step 3: Switch to gh-pages branch +print_info "Checking out gh-pages branch…" +git checkout gh-pages +if [ $? -ne 0 ]; then + print_error "Failed to checkout gh-pages branch. Make sure it exists." +fi +print_success "Switched to gh-pages branch" + +# Step 4: Create a new branch for the update +print_info "Creating new branch ${NEW_BRANCH}…" +execute "git checkout -b ${NEW_BRANCH}" + +# Step 5: Move root files +print_info "Moving root files from temporary location…" +ROOT_FILES=("404.html" "CNAME" "apple-touch-icon.png" "favicon.ico" "index.html" "robots.txt" "sitemap-0.xml" "sitemap-index.xml" "sw.js") +for file in "${ROOT_FILES[@]}"; do + if [ -f "/tmp/_site/$file" ]; then + execute "mv /tmp/_site/$file ." + else + print_warning "File /tmp/_site/$file not found. Skipping." + fi +done + +# Step 6: Move directories with cleanup +print_info "Moving directories from temporary location…" +DIRS=("about" "components" "docsref" "examples" "getting-started" "migration") +for dir in "${DIRS[@]}"; do + if [ -d "/tmp/_site/$dir" ]; then + if [ -d "$dir" ]; then + execute "rm -rf $dir" + fi + execute "mv /tmp/_site/$dir ." + else + print_warning "Directory /tmp/_site/$dir not found. Skipping." + fi +done + +# Step 7: Handle special doc directories +print_info "Handling special documentation directories…" +SPECIAL_DOCS=("docs/getting-started" "docs/versions") +for dir in "${SPECIAL_DOCS[@]}"; do + if [ -d "/tmp/_site/$dir" ]; then + if [ -d "$dir" ]; then + execute "rm -rf $dir" + fi + # Make sure parent directory exists + parent_dir=$(dirname "$dir") + mkdir -p "$parent_dir" + execute "mv /tmp/_site/$dir $parent_dir/" + else + print_warning "Directory /tmp/_site/$dir not found. Skipping." + fi +done + +# Step 8: Move docs index.html +if [ -f "/tmp/_site/docs/index.html" ]; then + execute "mv /tmp/_site/docs/index.html docs/index.html" +else + print_warning "File /tmp/_site/docs/index.html not found. Skipping." +fi + +# Step 9: Handle docs/5.3 +if [ -d "/tmp/_site/docs/5.3" ]; then + if [ -d "docs/5.3" ]; then + execute "rm -rf docs/5.3" + fi + execute "mv /tmp/_site/docs/5.3 docs/" +else + print_warning "Directory /tmp/_site/docs/5.3 not found. Skipping." +fi + +# Clean up remaining files in /tmp/_site if any +if [ -d "/tmp/_site" ]; then + remaining_files=$(find /tmp/_site -type f | wc -l) + remaining_dirs=$(find /tmp/_site -type d | wc -l) + if [ $remaining_files -gt 0 ] || [ $remaining_dirs -gt 1 ]; then + print_warning "There are still some files or directories in /tmp/_site that weren't moved." + print_warning "You may want to inspect /tmp/_site to see if anything important was missed." + else + print_info "Cleaning up temporary directory…" + rm -rf /tmp/_site + print_success "Temporary directory cleaned up" + fi +fi + +# Step 10: Remove empty site directory if it exists +if [ -d "site" ]; then + print_info "Removing empty site directory…" + execute "rm -rf site" +fi + +print_success "Docs prep complete!" +print_info "Review changes before committing and pushing." +print_info "Next steps:" +print_info " 1. Run a local server to review changes" +print_info " 2. Check browser and web inspector for any errors" +print_info " 3. git add ." +print_info " 4. git commit -m \"Update documentation\"" +print_info " 5. git push origin ${NEW_BRANCH}" diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/generate-sri.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/generate-sri.mjs new file mode 100644 index 00000000..5622843f --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/generate-sri.mjs @@ -0,0 +1,64 @@ +#!/usr/bin/env node + +/*! + * Script to generate SRI hashes for use in our docs. + * Remember to use the same vendor files as the CDN ones, + * otherwise the hashes won't match! + * + * Copyright 2017-2025 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ + +import crypto from 'node:crypto' +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import sh from 'shelljs' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +sh.config.fatal = true + +const configFile = path.join(__dirname, '../config.yml') + +// Array of objects which holds the files to generate SRI hashes for. +// `file` is the path from the root folder +// `configPropertyName` is the config.yml variable's name of the file +const files = [ + { + file: 'dist/css/bootstrap.min.css', + configPropertyName: 'css_hash' + }, + { + file: 'dist/css/bootstrap.rtl.min.css', + configPropertyName: 'css_rtl_hash' + }, + { + file: 'dist/js/bootstrap.min.js', + configPropertyName: 'js_hash' + }, + { + file: 'dist/js/bootstrap.bundle.min.js', + configPropertyName: 'js_bundle_hash' + }, + { + file: 'node_modules/@popperjs/core/dist/umd/popper.min.js', + configPropertyName: 'popper_hash' + } +] + +for (const { file, configPropertyName } of files) { + fs.readFile(file, 'utf8', (error, data) => { + if (error) { + throw error + } + + const algorithm = 'sha384' + const hash = crypto.createHash(algorithm).update(data, 'utf8').digest('base64') + const integrity = `${algorithm}-${hash}` + + console.log(`${configPropertyName}: ${integrity}`) + + sh.sed('-i', new RegExp(`^(\\s+${configPropertyName}:\\s+["'])\\S*(["'])`), `$1${integrity}$2`, configFile) + }) +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/postcss.config.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/postcss.config.mjs new file mode 100644 index 00000000..7717cfc3 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/postcss.config.mjs @@ -0,0 +1,17 @@ +const mapConfig = { + inline: false, + annotation: true, + sourcesContent: true +} + +export default context => { + return { + map: context.file.dirname.includes('examples') ? false : mapConfig, + plugins: { + autoprefixer: { + cascade: false + }, + rtlcss: context.env === 'RTL' + } + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/rollup.config.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/rollup.config.mjs new file mode 100644 index 00000000..dd6c7d13 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/rollup.config.mjs @@ -0,0 +1,59 @@ +import path from 'node:path' +import process from 'node:process' +import { fileURLToPath } from 'node:url' +import { babel } from '@rollup/plugin-babel' +import { nodeResolve } from '@rollup/plugin-node-resolve' +import replace from '@rollup/plugin-replace' +import banner from './banner.mjs' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +const BUNDLE = process.env.BUNDLE === 'true' +const ESM = process.env.ESM === 'true' + +let destinationFile = `bootstrap${ESM ? '.esm' : ''}` +const external = ['@popperjs/core'] +const plugins = [ + babel({ + // Only transpile our source code + exclude: 'node_modules/**', + // Include the helpers in the bundle, at most one copy of each + babelHelpers: 'bundled' + }) +] +const globals = { + '@popperjs/core': 'Popper' +} + +if (BUNDLE) { + destinationFile += '.bundle' + // Remove last entry in external array to bundle Popper + external.pop() + delete globals['@popperjs/core'] + plugins.push( + replace({ + 'process.env.NODE_ENV': '"production"', + preventAssignment: true + }), + nodeResolve() + ) +} + +const rollupConfig = { + input: path.resolve(__dirname, `../js/index.${ESM ? 'esm' : 'umd'}.js`), + output: { + banner: banner(), + file: path.resolve(__dirname, `../dist/js/${destinationFile}.js`), + format: ESM ? 'esm' : 'umd', + globals, + generatedCode: 'es2015' + }, + external, + plugins +} + +if (!ESM) { + rollupConfig.output.name = 'bootstrap' +} + +export default rollupConfig diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/vnu-jar.mjs b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/vnu-jar.mjs new file mode 100644 index 00000000..4eedb1be --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/build/vnu-jar.mjs @@ -0,0 +1,66 @@ +#!/usr/bin/env node + +/*! + * Script to run vnu-jar if Java is available. + * Copyright 2017-2025 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ + +import { execFile, spawn } from 'node:child_process' +import vnu from 'vnu-jar' + +execFile('java', ['-version'], (error, stdout, stderr) => { + if (error) { + console.error('Skipping vnu-jar test; Java is probably missing.') + console.error(error) + return + } + + console.log('Running vnu-jar validation...') + + const is32bitJava = !/64-Bit/.test(stderr) + + // vnu-jar accepts multiple ignores joined with a `|`. + // Also note that the ignores are string regular expressions. + const ignores = [ + // "autocomplete" is included in + + + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle-modularity.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle-modularity.js new file mode 100644 index 00000000..63d65152 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle-modularity.js @@ -0,0 +1,17 @@ +'use strict' + +const commonjs = require('@rollup/plugin-commonjs') +const configRollup = require('./rollup.bundle.js') + +const config = { + ...configRollup, + input: 'js/tests/integration/bundle-modularity.js', + output: { + file: 'js/coverage/bundle-modularity.js', + format: 'iife' + } +} + +config.plugins.unshift(commonjs()) + +module.exports = config diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle.js new file mode 100644 index 00000000..8b3c578a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/integration/rollup.bundle.js @@ -0,0 +1,24 @@ +'use strict' + +const { babel } = require('@rollup/plugin-babel') +const { nodeResolve } = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') + +module.exports = { + input: 'js/tests/integration/bundle.js', + output: { + file: 'js/coverage/bundle.js', + format: 'iife' + }, + plugins: [ + replace({ + 'process.env.NODE_ENV': '"production"', + preventAssignment: true + }), + nodeResolve(), + babel({ + exclude: 'node_modules/**', + babelHelpers: 'bundled' + }) + ] +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/karma.conf.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/karma.conf.js new file mode 100644 index 00000000..36bf7f2d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/karma.conf.js @@ -0,0 +1,169 @@ +'use strict' + +const path = require('node:path') +const ip = require('ip') +const { babel } = require('@rollup/plugin-babel') +const istanbul = require('rollup-plugin-istanbul') +const { nodeResolve } = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') +const { browsers } = require('./browsers.js') + +const ENV = process.env +const BROWSERSTACK = Boolean(ENV.BROWSERSTACK) +const DEBUG = Boolean(ENV.DEBUG) +const JQUERY_TEST = Boolean(ENV.JQUERY) + +const frameworks = [ + 'jasmine' +] + +const plugins = [ + 'karma-jasmine', + 'karma-rollup-preprocessor' +] + +const reporters = ['dots'] + +const detectBrowsers = { + usePhantomJS: false, + postDetection(availableBrowser) { + // On CI just use Chrome + if (ENV.CI === true) { + return ['ChromeHeadless'] + } + + if (availableBrowser.includes('Chrome')) { + return DEBUG ? ['Chrome'] : ['ChromeHeadless'] + } + + if (availableBrowser.includes('Chromium')) { + return DEBUG ? ['Chromium'] : ['ChromiumHeadless'] + } + + if (availableBrowser.includes('Firefox')) { + return DEBUG ? ['Firefox'] : ['FirefoxHeadless'] + } + + throw new Error('Please install Chrome, Chromium or Firefox') + } +} + +const config = { + basePath: '../..', + port: 9876, + colors: true, + autoWatch: false, + singleRun: true, + concurrency: Number.POSITIVE_INFINITY, + client: { + clearContext: false + }, + files: [ + 'node_modules/hammer-simulator/index.js', + { + pattern: 'js/tests/unit/**/!(jquery).spec.js', + watched: !BROWSERSTACK + } + ], + preprocessors: { + 'js/tests/unit/**/*.spec.js': ['rollup'] + }, + rollupPreprocessor: { + plugins: [ + replace({ + 'process.env.NODE_ENV': '"dev"', + preventAssignment: true + }), + istanbul({ + exclude: [ + 'node_modules/**', + 'js/tests/unit/**/*.spec.js', + 'js/tests/helpers/**/*.js' + ] + }), + babel({ + // Only transpile our source code + exclude: 'node_modules/**', + // Inline the required helpers in each file + babelHelpers: 'inline' + }), + nodeResolve() + ], + output: { + format: 'iife', + name: 'bootstrapTest', + sourcemap: 'inline', + generatedCode: 'es2015' + } + } +} + +if (BROWSERSTACK) { + config.hostname = ip.address() + config.browserStack = { + username: ENV.BROWSER_STACK_USERNAME, + accessKey: ENV.BROWSER_STACK_ACCESS_KEY, + build: `bootstrap-${ENV.GITHUB_SHA ? `${ENV.GITHUB_SHA.slice(0, 7)}-` : ''}${new Date().toISOString()}`, + project: 'Bootstrap', + retryLimit: 2 + } + plugins.push('karma-browserstack-launcher', 'karma-jasmine-html-reporter') + config.customLaunchers = browsers + config.browsers = Object.keys(browsers) + reporters.push('BrowserStack', 'kjhtml') +} else if (JQUERY_TEST) { + frameworks.push('detectBrowsers') + plugins.push( + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-detect-browsers' + ) + config.detectBrowsers = detectBrowsers + config.files = [ + 'node_modules/jquery/dist/jquery.slim.min.js', + { + pattern: 'js/tests/unit/jquery.spec.js', + watched: false + } + ] +} else { + frameworks.push('detectBrowsers') + plugins.push( + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-detect-browsers', + 'karma-coverage-istanbul-reporter' + ) + reporters.push('coverage-istanbul') + config.detectBrowsers = detectBrowsers + config.coverageIstanbulReporter = { + dir: path.resolve(__dirname, '../coverage/'), + reports: ['lcov', 'text-summary'], + thresholds: { + emitWarning: false, + global: { + statements: 90, + branches: 89, + functions: 90, + lines: 90 + } + } + } + + if (DEBUG) { + config.hostname = ip.address() + plugins.push('karma-jasmine-html-reporter') + reporters.push('kjhtml') + config.singleRun = false + config.autoWatch = true + } +} + +config.frameworks = frameworks +config.plugins = plugins +config.reporters = reporters + +module.exports = karmaConfig => { + config.logLevel = karmaConfig.LOG_ERROR + karmaConfig.set(config) +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/alert.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/alert.spec.js new file mode 100644 index 00000000..97cc3cc5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/alert.spec.js @@ -0,0 +1,259 @@ +import Alert from '../../src/alert.js' +import { getTransitionDurationFromElement } from '../../src/util/index.js' +import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js' + +describe('Alert', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '
    ' + + const alertEl = fixtureEl.querySelector('.alert') + const alertBySelector = new Alert('.alert') + const alertByElement = new Alert(alertEl) + + expect(alertBySelector._element).toEqual(alertEl) + expect(alertByElement._element).toEqual(alertEl) + }) + + it('should return version', () => { + expect(Alert.VERSION).toEqual(jasmine.any(String)) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Alert.DATA_KEY).toEqual('bs.alert') + }) + }) + + describe('data-api', () => { + it('should close an alert without instantiating it manually', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const button = document.querySelector('button') + + button.click() + expect(document.querySelectorAll('.alert')).toHaveSize(0) + }) + + it('should close an alert without instantiating it manually with the parent selector', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const button = document.querySelector('button') + + button.click() + expect(document.querySelectorAll('.alert')).toHaveSize(0) + }) + }) + + describe('close', () => { + it('should close an alert', () => { + return new Promise(resolve => { + const spy = jasmine.createSpy('spy', getTransitionDurationFromElement) + fixtureEl.innerHTML = '
    ' + + const alertEl = document.querySelector('.alert') + const alert = new Alert(alertEl) + + alertEl.addEventListener('closed.bs.alert', () => { + expect(document.querySelectorAll('.alert')).toHaveSize(0) + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + alert.close() + }) + }) + + it('should close alert with fade class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const alertEl = document.querySelector('.alert') + const alert = new Alert(alertEl) + + alertEl.addEventListener('transitionend', () => { + expect().nothing() + }) + + alertEl.addEventListener('closed.bs.alert', () => { + expect(document.querySelectorAll('.alert')).toHaveSize(0) + resolve() + }) + + alert.close() + }) + }) + + it('should not remove alert if close event is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '
    ' + + const getAlert = () => document.querySelector('.alert') + const alertEl = getAlert() + const alert = new Alert(alertEl) + + alertEl.addEventListener('close.bs.alert', event => { + event.preventDefault() + setTimeout(() => { + expect(getAlert()).not.toBeNull() + resolve() + }, 10) + }) + + alertEl.addEventListener('closed.bs.alert', () => { + reject(new Error('should not fire closed event')) + }) + + alert.close() + }) + }) + }) + + describe('dispose', () => { + it('should dispose an alert', () => { + fixtureEl.innerHTML = '
    ' + + const alertEl = document.querySelector('.alert') + const alert = new Alert(alertEl) + + expect(Alert.getInstance(alertEl)).not.toBeNull() + + alert.dispose() + + expect(Alert.getInstance(alertEl)).toBeNull() + }) + }) + + describe('jQueryInterface', () => { + it('should handle config passed and toggle existing alert', () => { + fixtureEl.innerHTML = '
    ' + + const alertEl = fixtureEl.querySelector('.alert') + const alert = new Alert(alertEl) + + const spy = spyOn(alert, 'close') + + jQueryMock.fn.alert = Alert.jQueryInterface + jQueryMock.elements = [alertEl] + + jQueryMock.fn.alert.call(jQueryMock, 'close') + + expect(spy).toHaveBeenCalled() + }) + + it('should create new alert instance and call close', () => { + fixtureEl.innerHTML = '
    ' + + const alertEl = fixtureEl.querySelector('.alert') + + jQueryMock.fn.alert = Alert.jQueryInterface + jQueryMock.elements = [alertEl] + + expect(Alert.getInstance(alertEl)).toBeNull() + jQueryMock.fn.alert.call(jQueryMock, 'close') + + expect(fixtureEl.querySelector('.alert')).toBeNull() + }) + + it('should just create an alert instance without calling close', () => { + fixtureEl.innerHTML = '
    ' + + const alertEl = fixtureEl.querySelector('.alert') + + jQueryMock.fn.alert = Alert.jQueryInterface + jQueryMock.elements = [alertEl] + + jQueryMock.fn.alert.call(jQueryMock) + + expect(Alert.getInstance(alertEl)).not.toBeNull() + expect(fixtureEl.querySelector('.alert')).not.toBeNull() + }) + + it('should throw an error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.alert = Alert.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.alert.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should throw an error on protected method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = '_getConfig' + + jQueryMock.fn.alert = Alert.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.alert.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('getInstance', () => { + it('should return alert instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const alert = new Alert(div) + + expect(Alert.getInstance(div)).toEqual(alert) + expect(Alert.getInstance(div)).toBeInstanceOf(Alert) + }) + + it('should return null when there is no alert instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Alert.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return alert instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const alert = new Alert(div) + + expect(Alert.getOrCreateInstance(div)).toEqual(alert) + expect(Alert.getInstance(div)).toEqual(Alert.getOrCreateInstance(div, {})) + expect(Alert.getOrCreateInstance(div)).toBeInstanceOf(Alert) + }) + + it('should return new instance when there is no alert instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Alert.getInstance(div)).toBeNull() + expect(Alert.getOrCreateInstance(div)).toBeInstanceOf(Alert) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/base-component.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/base-component.spec.js new file mode 100644 index 00000000..5b7d52e2 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/base-component.spec.js @@ -0,0 +1,168 @@ +import BaseComponent from '../../src/base-component.js' +import EventHandler from '../../src/dom/event-handler.js' +import { noop } from '../../src/util/index.js' +import { clearFixture, getFixture } from '../helpers/fixture.js' + +class DummyClass extends BaseComponent { + constructor(element) { + super(element) + + EventHandler.on(this._element, `click${DummyClass.EVENT_KEY}`, noop) + } + + static get NAME() { + return 'dummy' + } +} + +describe('Base Component', () => { + let fixtureEl + const name = 'dummy' + let element + let instance + const createInstance = () => { + fixtureEl.innerHTML = '
    ' + element = fixtureEl.querySelector('#foo') + instance = new DummyClass(element) + } + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('Static Methods', () => { + describe('VERSION', () => { + it('should return version', () => { + expect(DummyClass.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(DummyClass.DATA_KEY).toEqual(`bs.${name}`) + }) + }) + + describe('NAME', () => { + it('should throw an Error if it is not initialized', () => { + expect(() => { + // eslint-disable-next-line no-unused-expressions + BaseComponent.NAME + }).toThrowError(Error) + }) + + it('should return plugin NAME', () => { + expect(DummyClass.NAME).toEqual(name) + }) + }) + + describe('EVENT_KEY', () => { + it('should return plugin event key', () => { + expect(DummyClass.EVENT_KEY).toEqual(`.bs.${name}`) + }) + }) + }) + + describe('Public Methods', () => { + describe('constructor', () => { + it('should accept element, either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ' + ].join('') + + const el = fixtureEl.querySelector('#foo') + const elInstance = new DummyClass(el) + const selectorInstance = new DummyClass('#bar') + + expect(elInstance._element).toEqual(el) + expect(selectorInstance._element).toEqual(fixtureEl.querySelector('#bar')) + }) + + it('should not initialize and add element record to Data (caching), if argument `element` is not an HTML element', () => { + fixtureEl.innerHTML = '' + + const el = fixtureEl.querySelector('#foo') + const elInstance = new DummyClass(el) + const selectorInstance = new DummyClass('#bar') + + expect(elInstance._element).not.toBeDefined() + expect(selectorInstance._element).not.toBeDefined() + }) + }) + + describe('dispose', () => { + it('should dispose an component', () => { + createInstance() + expect(DummyClass.getInstance(element)).not.toBeNull() + + instance.dispose() + + expect(DummyClass.getInstance(element)).toBeNull() + expect(instance._element).toBeNull() + }) + + it('should de-register element event listeners', () => { + createInstance() + const spy = spyOn(EventHandler, 'off') + + instance.dispose() + + expect(spy).toHaveBeenCalledWith(element, DummyClass.EVENT_KEY) + }) + }) + + describe('getInstance', () => { + it('should return an instance', () => { + createInstance() + + expect(DummyClass.getInstance(element)).toEqual(instance) + expect(DummyClass.getInstance(element)).toBeInstanceOf(DummyClass) + }) + + it('should accept element, either passed as a CSS selector, jQuery element, or DOM element', () => { + createInstance() + + expect(DummyClass.getInstance('#foo')).toEqual(instance) + expect(DummyClass.getInstance(element)).toEqual(instance) + + const fakejQueryObject = { + 0: element, + jquery: 'foo' + } + + expect(DummyClass.getInstance(fakejQueryObject)).toEqual(instance) + }) + + it('should return null when there is no instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(DummyClass.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return an instance', () => { + createInstance() + + expect(DummyClass.getOrCreateInstance(element)).toEqual(instance) + expect(DummyClass.getInstance(element)).toEqual(DummyClass.getOrCreateInstance(element, {})) + expect(DummyClass.getOrCreateInstance(element)).toBeInstanceOf(DummyClass) + }) + + it('should return new instance when there is no alert instance', () => { + fixtureEl.innerHTML = '
    ' + element = fixtureEl.querySelector('#foo') + + expect(DummyClass.getInstance(element)).toBeNull() + expect(DummyClass.getOrCreateInstance(element)).toBeInstanceOf(DummyClass) + }) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/button.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/button.spec.js new file mode 100644 index 00000000..6624fee7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/button.spec.js @@ -0,0 +1,183 @@ +import Button from '../../src/button.js' +import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js' + +describe('Button', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '' + const buttonEl = fixtureEl.querySelector('[data-bs-toggle="button"]') + const buttonBySelector = new Button('[data-bs-toggle="button"]') + const buttonByElement = new Button(buttonEl) + + expect(buttonBySelector._element).toEqual(buttonEl) + expect(buttonByElement._element).toEqual(buttonEl) + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Button.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Button.DATA_KEY).toEqual('bs.button') + }) + }) + + describe('data-api', () => { + it('should toggle active class on click', () => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelector('.test') + const btnTestParent = fixtureEl.querySelector('.testParent') + + expect(btn).not.toHaveClass('active') + + btn.click() + + expect(btn).toHaveClass('active') + + btn.click() + + expect(btn).not.toHaveClass('active') + + divTest.click() + + expect(btnTestParent).toHaveClass('active') + }) + }) + + describe('toggle', () => { + it('should toggle aria-pressed', () => { + fixtureEl.innerHTML = '' + + const btnEl = fixtureEl.querySelector('.btn') + const button = new Button(btnEl) + + expect(btnEl.getAttribute('aria-pressed')).toEqual('false') + expect(btnEl).not.toHaveClass('active') + + button.toggle() + + expect(btnEl.getAttribute('aria-pressed')).toEqual('true') + expect(btnEl).toHaveClass('active') + }) + }) + + describe('dispose', () => { + it('should dispose a button', () => { + fixtureEl.innerHTML = '' + + const btnEl = fixtureEl.querySelector('.btn') + const button = new Button(btnEl) + + expect(Button.getInstance(btnEl)).not.toBeNull() + + button.dispose() + + expect(Button.getInstance(btnEl)).toBeNull() + }) + }) + + describe('jQueryInterface', () => { + it('should handle config passed and toggle existing button', () => { + fixtureEl.innerHTML = '' + + const btnEl = fixtureEl.querySelector('.btn') + const button = new Button(btnEl) + + const spy = spyOn(button, 'toggle') + + jQueryMock.fn.button = Button.jQueryInterface + jQueryMock.elements = [btnEl] + + jQueryMock.fn.button.call(jQueryMock, 'toggle') + + expect(spy).toHaveBeenCalled() + }) + + it('should create new button instance and call toggle', () => { + fixtureEl.innerHTML = '' + + const btnEl = fixtureEl.querySelector('.btn') + + jQueryMock.fn.button = Button.jQueryInterface + jQueryMock.elements = [btnEl] + + jQueryMock.fn.button.call(jQueryMock, 'toggle') + + expect(Button.getInstance(btnEl)).not.toBeNull() + expect(btnEl).toHaveClass('active') + }) + + it('should just create a button instance without calling toggle', () => { + fixtureEl.innerHTML = '' + + const btnEl = fixtureEl.querySelector('.btn') + + jQueryMock.fn.button = Button.jQueryInterface + jQueryMock.elements = [btnEl] + + jQueryMock.fn.button.call(jQueryMock) + + expect(Button.getInstance(btnEl)).not.toBeNull() + expect(btnEl).not.toHaveClass('active') + }) + }) + + describe('getInstance', () => { + it('should return button instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const button = new Button(div) + + expect(Button.getInstance(div)).toEqual(button) + expect(Button.getInstance(div)).toBeInstanceOf(Button) + }) + + it('should return null when there is no button instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Button.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return button instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const button = new Button(div) + + expect(Button.getOrCreateInstance(div)).toEqual(button) + expect(Button.getInstance(div)).toEqual(Button.getOrCreateInstance(div, {})) + expect(Button.getOrCreateInstance(div)).toBeInstanceOf(Button) + }) + + it('should return new instance when there is no button instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Button.getInstance(div)).toBeNull() + expect(Button.getOrCreateInstance(div)).toBeInstanceOf(Button) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/carousel.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/carousel.spec.js new file mode 100644 index 00000000..2960eb5c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/carousel.spec.js @@ -0,0 +1,1572 @@ +import Carousel from '../../src/carousel.js' +import EventHandler from '../../src/dom/event-handler.js' +import { isRTL, noop } from '../../src/util/index.js' +import Swipe from '../../src/util/swipe.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Carousel', () => { + const { Simulator, PointerEvent } = window + const originWinPointerEvent = PointerEvent + const supportPointerEvent = Boolean(PointerEvent) + + const cssStyleCarousel = '.carousel.pointer-event { touch-action: none; }' + + const stylesCarousel = document.createElement('style') + stylesCarousel.type = 'text/css' + stylesCarousel.append(document.createTextNode(cssStyleCarousel)) + + const clearPointerEvents = () => { + window.PointerEvent = null + } + + const restorePointerEvents = () => { + window.PointerEvent = originWinPointerEvent + } + + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Carousel.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Carousel.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Carousel.DATA_KEY).toEqual('bs.carousel') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '' + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carouselBySelector = new Carousel('#myCarousel') + const carouselByElement = new Carousel(carouselEl) + + expect(carouselBySelector._element).toEqual(carouselEl) + expect(carouselByElement._element).toEqual(carouselEl) + }) + + it('should start cycling if `ride`===`carousel`', () => { + fixtureEl.innerHTML = '' + + const carousel = new Carousel('#myCarousel') + expect(carousel._interval).not.toBeNull() + }) + + it('should not start cycling if `ride`!==`carousel`', () => { + fixtureEl.innerHTML = '' + + const carousel = new Carousel('#myCarousel') + expect(carousel._interval).toBeNull() + }) + + it('should go to next item if right arrow key is pressed', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, { + keyboard: true + }) + + const spy = spyOn(carousel, '_keydown').and.callThrough() + + carouselEl.addEventListener('slid.bs.carousel', () => { + expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item2')) + expect(spy).toHaveBeenCalled() + resolve() + }) + + const keydown = createEvent('keydown') + keydown.key = 'ArrowRight' + + carouselEl.dispatchEvent(keydown) + }) + }) + + it('should ignore keyboard events if data-bs-keyboard=false', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const spy = spyOn(EventHandler, 'trigger').and.callThrough() + const carouselEl = fixtureEl.querySelector('#myCarousel') + // eslint-disable-next-line no-new + new Carousel('#myCarousel') + expect(spy).not.toHaveBeenCalledWith(carouselEl, 'keydown.bs.carousel', jasmine.any(Function)) + }) + + it('should ignore mouse events if data-bs-pause=false', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const spy = spyOn(EventHandler, 'trigger').and.callThrough() + const carouselEl = fixtureEl.querySelector('#myCarousel') + // eslint-disable-next-line no-new + new Carousel('#myCarousel') + expect(spy).not.toHaveBeenCalledWith(carouselEl, 'hover.bs.carousel', jasmine.any(Function)) + }) + + it('should go to previous item if left arrow key is pressed', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, { + keyboard: true + }) + + const spy = spyOn(carousel, '_keydown').and.callThrough() + + carouselEl.addEventListener('slid.bs.carousel', () => { + expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item1')) + expect(spy).toHaveBeenCalled() + resolve() + }) + + const keydown = createEvent('keydown') + keydown.key = 'ArrowLeft' + + carouselEl.dispatchEvent(keydown) + }) + }) + + it('should not prevent keydown if key is not ARROW_LEFT or ARROW_RIGHT', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, { + keyboard: true + }) + + const spy = spyOn(carousel, '_keydown').and.callThrough() + + carouselEl.addEventListener('keydown', event => { + expect(spy).toHaveBeenCalled() + expect(event.defaultPrevented).toBeFalse() + resolve() + }) + + const keydown = createEvent('keydown') + keydown.key = 'ArrowDown' + + carouselEl.dispatchEvent(keydown) + }) + }) + + it('should ignore keyboard events within s and ', + ' ', + ' ', + ' ', + ' ', + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const input = fixtureEl.querySelector('input') + const textarea = fixtureEl.querySelector('textarea') + const carousel = new Carousel(carouselEl, { + keyboard: true + }) + + const spyKeydown = spyOn(carousel, '_keydown').and.callThrough() + const spySlide = spyOn(carousel, '_slide') + + const keydown = createEvent('keydown', { bubbles: true, cancelable: true }) + keydown.key = 'ArrowRight' + Object.defineProperty(keydown, 'target', { + value: input, + writable: true, + configurable: true + }) + + input.dispatchEvent(keydown) + + expect(spyKeydown).toHaveBeenCalled() + expect(spySlide).not.toHaveBeenCalled() + + spyKeydown.calls.reset() + spySlide.calls.reset() + + Object.defineProperty(keydown, 'target', { + value: textarea + }) + textarea.dispatchEvent(keydown) + + expect(spyKeydown).toHaveBeenCalled() + expect(spySlide).not.toHaveBeenCalled() + }) + + it('should not slide if arrow key is pressed and carousel is sliding', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + + const spy = spyOn(EventHandler, 'trigger') + + carousel._isSliding = true + + for (const key of ['ArrowLeft', 'ArrowRight']) { + const keydown = createEvent('keydown') + keydown.key = key + + carouselEl.dispatchEvent(keydown) + } + + expect(spy).not.toHaveBeenCalled() + }) + + it('should wrap around from end to start when wrap option is true', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, { wrap: true }) + const getActiveId = () => carouselEl.querySelector('.carousel-item.active').getAttribute('id') + + carouselEl.addEventListener('slid.bs.carousel', event => { + const activeId = getActiveId() + + if (activeId === 'two') { + carousel.next() + return + } + + if (activeId === 'three') { + carousel.next() + return + } + + if (activeId === 'one') { + // carousel wrapped around and slid from 3rd to 1st slide + expect(activeId).toEqual('one') + expect(event.from + 1).toEqual(3) + resolve() + } + }) + + carousel.next() + }) + }) + + it('should stay at the start when the prev method is called and wrap is false', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const firstElement = fixtureEl.querySelector('#one') + const carousel = new Carousel(carouselEl, { wrap: false }) + + carouselEl.addEventListener('slid.bs.carousel', () => { + reject(new Error('carousel slid when it should not have slid')) + }) + + carousel.prev() + + setTimeout(() => { + expect(firstElement).toHaveClass('active') + resolve() + }, 10) + }) + }) + + it('should not add touch event listeners if touch = false', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + + const spy = spyOn(Carousel.prototype, '_addTouchEventListeners') + + const carousel = new Carousel(carouselEl, { + touch: false + }) + + expect(spy).not.toHaveBeenCalled() + expect(carousel._swipeHelper).toBeNull() + }) + + it('should not add touch event listeners if touch supported = false', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + spyOn(Swipe, 'isSupported').and.returnValue(false) + + const carousel = new Carousel(carouselEl) + EventHandler.off(carouselEl, Carousel.EVENT_KEY) + + const spy = spyOn(carousel, '_addTouchEventListeners') + + carousel._addEventListeners() + + expect(spy).not.toHaveBeenCalled() + expect(carousel._swipeHelper).toBeNull() + }) + + it('should add touch event listeners by default', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + + spyOn(Carousel.prototype, '_addTouchEventListeners') + + // Headless browser does not support touch events, so need to fake it + // to test that touch events are add properly. + document.documentElement.ontouchstart = noop + const carousel = new Carousel(carouselEl) + + expect(carousel._addTouchEventListeners).toHaveBeenCalled() + }) + + it('should allow swiperight and call _slide (prev) with pointer events', () => { + return new Promise(resolve => { + if (!supportPointerEvent) { + expect().nothing() + resolve() + return + } + + document.documentElement.ontouchstart = noop + document.head.append(stylesCarousel) + Simulator.setType('pointer') + + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('.carousel') + const item = fixtureEl.querySelector('#item') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(carousel, '_slide').and.callThrough() + + carouselEl.addEventListener('slid.bs.carousel', event => { + expect(item).toHaveClass('active') + expect(spy).toHaveBeenCalledWith('prev') + expect(event.direction).toEqual('right') + stylesCarousel.remove() + delete document.documentElement.ontouchstart + resolve() + }) + + Simulator.gestures.swipe(carouselEl, { + deltaX: 300, + deltaY: 0 + }) + }) + }) + + it('should allow swipeleft and call next with pointer events', () => { + return new Promise(resolve => { + if (!supportPointerEvent) { + expect().nothing() + resolve() + return + } + + document.documentElement.ontouchstart = noop + document.head.append(stylesCarousel) + Simulator.setType('pointer') + + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('.carousel') + const item = fixtureEl.querySelector('#item') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(carousel, '_slide').and.callThrough() + + carouselEl.addEventListener('slid.bs.carousel', event => { + expect(item).not.toHaveClass('active') + expect(spy).toHaveBeenCalledWith('next') + expect(event.direction).toEqual('left') + stylesCarousel.remove() + delete document.documentElement.ontouchstart + resolve() + }) + + Simulator.gestures.swipe(carouselEl, { + pos: [300, 10], + deltaX: -300, + deltaY: 0 + }) + }) + }) + + it('should allow swiperight and call _slide (prev) with touch events', () => { + return new Promise(resolve => { + Simulator.setType('touch') + clearPointerEvents() + document.documentElement.ontouchstart = noop + + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('.carousel') + const item = fixtureEl.querySelector('#item') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(carousel, '_slide').and.callThrough() + + carouselEl.addEventListener('slid.bs.carousel', event => { + expect(item).toHaveClass('active') + expect(spy).toHaveBeenCalledWith('prev') + expect(event.direction).toEqual('right') + delete document.documentElement.ontouchstart + restorePointerEvents() + resolve() + }) + + Simulator.gestures.swipe(carouselEl, { + deltaX: 300, + deltaY: 0 + }) + }) + }) + + it('should allow swipeleft and call _slide (next) with touch events', () => { + return new Promise(resolve => { + Simulator.setType('touch') + clearPointerEvents() + document.documentElement.ontouchstart = noop + + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('.carousel') + const item = fixtureEl.querySelector('#item') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(carousel, '_slide').and.callThrough() + + carouselEl.addEventListener('slid.bs.carousel', event => { + expect(item).not.toHaveClass('active') + expect(spy).toHaveBeenCalledWith('next') + expect(event.direction).toEqual('left') + delete document.documentElement.ontouchstart + restorePointerEvents() + resolve() + }) + + Simulator.gestures.swipe(carouselEl, { + pos: [300, 10], + deltaX: -300, + deltaY: 0 + }) + }) + }) + + it('should not slide when swiping and carousel is sliding', () => { + return new Promise(resolve => { + Simulator.setType('touch') + clearPointerEvents() + document.documentElement.ontouchstart = noop + + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('.carousel') + const carousel = new Carousel(carouselEl) + carousel._isSliding = true + + const spy = spyOn(EventHandler, 'trigger') + + Simulator.gestures.swipe(carouselEl, { + deltaX: 300, + deltaY: 0 + }) + + Simulator.gestures.swipe(carouselEl, { + pos: [300, 10], + deltaX: -300, + deltaY: 0 + }) + + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + delete document.documentElement.ontouchstart + restorePointerEvents() + resolve() + }, 300) + }) + }) + + it('should not allow pinch with touch events', () => { + return new Promise(resolve => { + Simulator.setType('touch') + clearPointerEvents() + document.documentElement.ontouchstart = noop + + fixtureEl.innerHTML = '' + + const carouselEl = fixtureEl.querySelector('.carousel') + const carousel = new Carousel(carouselEl) + + Simulator.gestures.swipe(carouselEl, { + pos: [300, 10], + deltaX: -300, + deltaY: 0, + touches: 2 + }, () => { + restorePointerEvents() + delete document.documentElement.ontouchstart + expect(carousel._swipeHelper._deltaX).toEqual(0) + resolve() + }) + }) + }) + + it('should call pause method on mouse over with pause equal to hover', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const carouselEl = fixtureEl.querySelector('.carousel') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(carousel, 'pause') + + const mouseOverEvent = createEvent('mouseover') + carouselEl.dispatchEvent(mouseOverEvent) + + setTimeout(() => { + expect(spy).toHaveBeenCalled() + resolve() + }, 10) + }) + }) + + it('should call `maybeEnableCycle` on mouse out with pause equal to hover', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const carouselEl = fixtureEl.querySelector('.carousel') + const carousel = new Carousel(carouselEl) + + const spyEnable = spyOn(carousel, '_maybeEnableCycle').and.callThrough() + const spyCycle = spyOn(carousel, 'cycle') + + const mouseOutEvent = createEvent('mouseout') + carouselEl.dispatchEvent(mouseOutEvent) + + setTimeout(() => { + expect(spyEnable).toHaveBeenCalled() + expect(spyCycle).toHaveBeenCalled() + resolve() + }, 10) + }) + }) + }) + + describe('next', () => { + it('should not slide if the carousel is sliding', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + + const spy = spyOn(EventHandler, 'trigger') + + carousel._isSliding = true + carousel.next() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should not fire slid when slide is prevented', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + let slidEvent = false + + const doneTest = () => { + setTimeout(() => { + expect(slidEvent).toBeFalse() + resolve() + }, 20) + } + + carouselEl.addEventListener('slide.bs.carousel', event => { + event.preventDefault() + doneTest() + }) + + carouselEl.addEventListener('slid.bs.carousel', () => { + slidEvent = true + }) + + carousel.next() + }) + }) + + it('should fire slide event with: direction, relatedTarget, from and to', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + const onSlide = event => { + expect(event.direction).toEqual('left') + expect(event.relatedTarget).toHaveClass('carousel-item') + expect(event.from).toEqual(0) + expect(event.to).toEqual(1) + + carouselEl.removeEventListener('slide.bs.carousel', onSlide) + carouselEl.addEventListener('slide.bs.carousel', onSlide2) + + carousel.prev() + } + + const onSlide2 = event => { + expect(event.direction).toEqual('right') + resolve() + } + + carouselEl.addEventListener('slide.bs.carousel', onSlide) + carousel.next() + }) + }) + + it('should fire slid event with: direction, relatedTarget, from and to', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + const onSlid = event => { + expect(event.direction).toEqual('left') + expect(event.relatedTarget).toHaveClass('carousel-item') + expect(event.from).toEqual(0) + expect(event.to).toEqual(1) + + carouselEl.removeEventListener('slid.bs.carousel', onSlid) + carouselEl.addEventListener('slid.bs.carousel', onSlid2) + + carousel.prev() + } + + const onSlid2 = event => { + expect(event.direction).toEqual('right') + resolve() + } + + carouselEl.addEventListener('slid.bs.carousel', onSlid) + carousel.next() + }) + }) + + it('should update the active element to the next item before sliding', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const secondItemEl = fixtureEl.querySelector('#secondItem') + const carousel = new Carousel(carouselEl) + + carousel.next() + + expect(carousel._activeElement).toEqual(secondItemEl) + }) + + it('should continue cycling if it was already', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl) + const spy = spyOn(carousel, 'cycle') + + carousel.next() + expect(spy).not.toHaveBeenCalled() + + carousel.cycle() + carousel.next() + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should update indicators if present', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const firstIndicator = fixtureEl.querySelector('#firstIndicator') + const secondIndicator = fixtureEl.querySelector('#secondIndicator') + const carousel = new Carousel(carouselEl) + + carouselEl.addEventListener('slid.bs.carousel', () => { + expect(firstIndicator).not.toHaveClass('active') + expect(firstIndicator.hasAttribute('aria-current')).toBeFalse() + expect(secondIndicator).toHaveClass('active') + expect(secondIndicator.getAttribute('aria-current')).toEqual('true') + resolve() + }) + + carousel.next() + }) + }) + + it('should call next()/prev() instance methods when clicking the respective direction buttons', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#carousel') + const prevBtnEl = fixtureEl.querySelector('.carousel-control-prev') + const nextBtnEl = fixtureEl.querySelector('.carousel-control-next') + + const carousel = new Carousel(carouselEl) + const nextSpy = spyOn(carousel, 'next') + const prevSpy = spyOn(carousel, 'prev') + const spyEnable = spyOn(carousel, '_maybeEnableCycle') + + nextBtnEl.click() + prevBtnEl.click() + + expect(nextSpy).toHaveBeenCalled() + expect(prevSpy).toHaveBeenCalled() + expect(spyEnable).toHaveBeenCalled() + }) + }) + + describe('nextWhenVisible', () => { + it('should not call next when the page is not visible', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const carouselEl = fixtureEl.querySelector('.carousel') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(carousel, 'next') + + carousel.nextWhenVisible() + + expect(spy).not.toHaveBeenCalled() + }) + }) + + describe('prev', () => { + it('should not slide if the carousel is sliding', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + + const spy = spyOn(EventHandler, 'trigger') + + carousel._isSliding = true + carousel.prev() + + expect(spy).not.toHaveBeenCalled() + }) + }) + + describe('pause', () => { + it('should trigger transitionend if the carousel have carousel-item-next or carousel-item-prev class, cause is sliding', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl) + const spy = spyOn(carousel, '_clearInterval') + + carouselEl.addEventListener('transitionend', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + carousel._slide('next') + carousel.pause() + }) + }) + }) + + describe('cycle', () => { + it('should set an interval', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl) + + const spy = spyOn(window, 'setInterval').and.callThrough() + + carousel.cycle() + + expect(spy).toHaveBeenCalled() + }) + + it('should clear interval if there is one', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl) + + carousel._interval = setInterval(noop, 10) + + const spySet = spyOn(window, 'setInterval').and.callThrough() + const spyClear = spyOn(window, 'clearInterval').and.callThrough() + + carousel.cycle() + + expect(spySet).toHaveBeenCalled() + expect(spyClear).toHaveBeenCalled() + }) + + it('should get interval from data attribute on the active item element', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const secondItemEl = fixtureEl.querySelector('#secondItem') + const carousel = new Carousel(carouselEl, { + interval: 1814 + }) + + expect(carousel._config.interval).toEqual(1814) + + carousel.cycle() + + expect(carousel._config.interval).toEqual(7) + + carousel._activeElement = secondItemEl + carousel.cycle() + + expect(carousel._config.interval).toEqual(9385) + }) + }) + + describe('to', () => { + it('should go directly to the provided index', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item1')) + + carousel.to(2) + + carouselEl.addEventListener('slid.bs.carousel', () => { + expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item3')) + resolve() + }) + }) + }) + + it('should return to a previous slide if the provided index is lower than the current', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item3')) + + carousel.to(1) + + carouselEl.addEventListener('slid.bs.carousel', () => { + expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item2')) + resolve() + }) + }) + }) + + it('should do nothing if a wrong index is provided', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + const spy = spyOn(carousel, '_slide') + + carousel.to(25) + + expect(spy).not.toHaveBeenCalled() + + spy.calls.reset() + + carousel.to(-5) + + expect(spy).not.toHaveBeenCalled() + }) + + it('should not continue if the provided is the same compare to the current one', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + const spy = spyOn(carousel, '_slide') + + carousel.to(0) + + expect(spy).not.toHaveBeenCalled() + }) + + it('should wait before performing to if a slide is sliding', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const carousel = new Carousel(carouselEl, {}) + + const spyOne = spyOn(EventHandler, 'one').and.callThrough() + const spySlide = spyOn(carousel, '_slide') + + carousel._isSliding = true + carousel.to(1) + + expect(spySlide).not.toHaveBeenCalled() + expect(spyOne).toHaveBeenCalled() + + const spyTo = spyOn(carousel, 'to') + + EventHandler.trigger(carouselEl, 'slid.bs.carousel') + + setTimeout(() => { + expect(spyTo).toHaveBeenCalledWith(1) + resolve() + }) + }) + }) + }) + + describe('rtl function', () => { + it('"_directionToOrder" and "_orderToDirection" must return the right results', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + + expect(carousel._directionToOrder('left')).toEqual('next') + expect(carousel._directionToOrder('right')).toEqual('prev') + + expect(carousel._orderToDirection('next')).toEqual('left') + expect(carousel._orderToDirection('prev')).toEqual('right') + }) + + it('"_directionToOrder" and "_orderToDirection" must return the right results when rtl=true', () => { + document.documentElement.dir = 'rtl' + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + expect(isRTL()).toBeTrue() + + expect(carousel._directionToOrder('left')).toEqual('prev') + expect(carousel._directionToOrder('right')).toEqual('next') + + expect(carousel._orderToDirection('next')).toEqual('right') + expect(carousel._orderToDirection('prev')).toEqual('left') + document.documentElement.dir = 'ltl' + }) + + it('"_slide" has to call _directionToOrder and "_orderToDirection"', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + + const spy = spyOn(carousel, '_orderToDirection').and.callThrough() + + carousel._slide(carousel._directionToOrder('left')) + expect(spy).toHaveBeenCalledWith('next') + + carousel._slide(carousel._directionToOrder('right')) + expect(spy).toHaveBeenCalledWith('prev') + }) + + it('"_slide" has to call "_directionToOrder" and "_orderToDirection" when rtl=true', () => { + document.documentElement.dir = 'rtl' + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const carousel = new Carousel(carouselEl, {}) + const spy = spyOn(carousel, '_orderToDirection').and.callThrough() + + carousel._slide(carousel._directionToOrder('left')) + expect(spy).toHaveBeenCalledWith('prev') + + carousel._slide(carousel._directionToOrder('right')) + expect(spy).toHaveBeenCalledWith('next') + + document.documentElement.dir = 'ltl' + }) + }) + + describe('dispose', () => { + it('should destroy a carousel', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const carouselEl = fixtureEl.querySelector('#myCarousel') + const addEventSpy = spyOn(carouselEl, 'addEventListener').and.callThrough() + const removeEventSpy = spyOn(EventHandler, 'off').and.callThrough() + + // Headless browser does not support touch events, so need to fake it + // to test that touch events are add/removed properly. + document.documentElement.ontouchstart = noop + + const carousel = new Carousel(carouselEl) + const swipeHelperSpy = spyOn(carousel._swipeHelper, 'dispose').and.callThrough() + + const expectedArgs = [ + ['keydown', jasmine.any(Function), jasmine.any(Boolean)], + ['mouseover', jasmine.any(Function), jasmine.any(Boolean)], + ['mouseout', jasmine.any(Function), jasmine.any(Boolean)], + ...(carousel._swipeHelper._supportPointerEvents ? + [ + ['pointerdown', jasmine.any(Function), jasmine.any(Boolean)], + ['pointerup', jasmine.any(Function), jasmine.any(Boolean)] + ] : + [ + ['touchstart', jasmine.any(Function), jasmine.any(Boolean)], + ['touchmove', jasmine.any(Function), jasmine.any(Boolean)], + ['touchend', jasmine.any(Function), jasmine.any(Boolean)] + ]) + ] + + expect(addEventSpy.calls.allArgs()).toEqual(expectedArgs) + + carousel.dispose() + + expect(carousel._swipeHelper).toBeNull() + expect(removeEventSpy).toHaveBeenCalledWith(carouselEl, Carousel.EVENT_KEY) + expect(swipeHelperSpy).toHaveBeenCalled() + + delete document.documentElement.ontouchstart + }) + }) + + describe('getInstance', () => { + it('should return carousel instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const carousel = new Carousel(div) + + expect(Carousel.getInstance(div)).toEqual(carousel) + expect(Carousel.getInstance(div)).toBeInstanceOf(Carousel) + }) + + it('should return null when there is no carousel instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Carousel.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return carousel instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const carousel = new Carousel(div) + + expect(Carousel.getOrCreateInstance(div)).toEqual(carousel) + expect(Carousel.getInstance(div)).toEqual(Carousel.getOrCreateInstance(div, {})) + expect(Carousel.getOrCreateInstance(div)).toBeInstanceOf(Carousel) + }) + + it('should return new instance when there is no carousel instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Carousel.getInstance(div)).toBeNull() + expect(Carousel.getOrCreateInstance(div)).toBeInstanceOf(Carousel) + }) + + it('should return new instance when there is no carousel instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Carousel.getInstance(div)).toBeNull() + const carousel = Carousel.getOrCreateInstance(div, { + interval: 1 + }) + expect(carousel).toBeInstanceOf(Carousel) + + expect(carousel._config.interval).toEqual(1) + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const carousel = new Carousel(div, { + interval: 1 + }) + expect(Carousel.getInstance(div)).toEqual(carousel) + + const carousel2 = Carousel.getOrCreateInstance(div, { + interval: 2 + }) + expect(carousel).toBeInstanceOf(Carousel) + expect(carousel2).toEqual(carousel) + + expect(carousel2._config.interval).toEqual(1) + }) + }) + + describe('jQueryInterface', () => { + it('should create a carousel', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.carousel = Carousel.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.carousel.call(jQueryMock) + + expect(Carousel.getInstance(div)).not.toBeNull() + }) + + it('should not re create a carousel', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const carousel = new Carousel(div) + + jQueryMock.fn.carousel = Carousel.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.carousel.call(jQueryMock) + + expect(Carousel.getInstance(div)).toEqual(carousel) + }) + + it('should call to if the config is a number', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const carousel = new Carousel(div) + const slideTo = 2 + + const spy = spyOn(carousel, 'to') + + jQueryMock.fn.carousel = Carousel.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.carousel.call(jQueryMock, slideTo) + + expect(spy).toHaveBeenCalledWith(slideTo) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.carousel = Carousel.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.carousel.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('data-api', () => { + it('should init carousels with data-bs-ride="carousel" on load', () => { + fixtureEl.innerHTML = '
    ' + + const carouselEl = fixtureEl.querySelector('div') + const loadEvent = createEvent('load') + + window.dispatchEvent(loadEvent) + const carousel = Carousel.getInstance(carouselEl) + expect(carousel._interval).not.toBeNull() + }) + + it('should create carousel and go to the next slide on click (with real button controls)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const next = fixtureEl.querySelector('#next') + const item2 = fixtureEl.querySelector('#item2') + + next.click() + + setTimeout(() => { + expect(item2).toHaveClass('active') + resolve() + }, 10) + }) + }) + + it('should create carousel and go to the next slide on click (using links as controls)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const next = fixtureEl.querySelector('#next') + const item2 = fixtureEl.querySelector('#item2') + + next.click() + + setTimeout(() => { + expect(item2).toHaveClass('active') + resolve() + }, 10) + }) + }) + + it('should create carousel and go to the next slide on click with data-bs-slide-to', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const next = fixtureEl.querySelector('#next') + const item2 = fixtureEl.querySelector('#item2') + + next.click() + + setTimeout(() => { + expect(item2).toHaveClass('active') + expect(Carousel.getInstance('#myCarousel')._interval).not.toBeNull() + resolve() + }, 10) + }) + }) + + it('should do nothing if no selector on click on arrows', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const next = fixtureEl.querySelector('#next') + + next.click() + + expect().nothing() + }) + + it('should do nothing if no carousel class on click on arrows', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + ' ', + '
    ' + ].join('') + + const next = fixtureEl.querySelector('#next') + + next.click() + + expect().nothing() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/collapse.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/collapse.spec.js new file mode 100644 index 00000000..58c53675 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/collapse.spec.js @@ -0,0 +1,1062 @@ +import Collapse from '../../src/collapse.js' +import EventHandler from '../../src/dom/event-handler.js' +import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js' + +describe('Collapse', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Collapse.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Collapse.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Collapse.DATA_KEY).toEqual('bs.collapse') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div.my-collapse') + const collapseBySelector = new Collapse('div.my-collapse') + const collapseByElement = new Collapse(collapseEl) + + expect(collapseBySelector._element).toEqual(collapseEl) + expect(collapseByElement._element).toEqual(collapseEl) + }) + + it('should allow jquery object in parent config', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' Toggle item', + '
    Lorem ipsum
    ', + '
    ', + '
    ' + ].join('') + + const collapseEl = fixtureEl.querySelector('div.collapse') + const myCollapseEl = fixtureEl.querySelector('.my-collapse') + const fakejQueryObject = { + 0: myCollapseEl, + jquery: 'foo' + } + const collapse = new Collapse(collapseEl, { + parent: fakejQueryObject + }) + + expect(collapse._config.parent).toEqual(myCollapseEl) + }) + + it('should allow non jquery object in parent config', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' Toggle item', + '
    Lorem ipsum
    ', + '
    ', + '
    ' + ].join('') + + const collapseEl = fixtureEl.querySelector('div.collapse') + const myCollapseEl = fixtureEl.querySelector('.my-collapse') + const collapse = new Collapse(collapseEl, { + parent: myCollapseEl + }) + + expect(collapse._config.parent).toEqual(myCollapseEl) + }) + + it('should allow string selector in parent config', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' Toggle item', + '
    Lorem ipsum
    ', + '
    ', + '
    ' + ].join('') + + const collapseEl = fixtureEl.querySelector('div.collapse') + const myCollapseEl = fixtureEl.querySelector('.my-collapse') + const collapse = new Collapse(collapseEl, { + parent: 'div.my-collapse' + }) + + expect(collapse._config.parent).toEqual(myCollapseEl) + }) + }) + + describe('toggle', () => { + it('should call show method if show class is not present', () => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl) + + const spy = spyOn(collapse, 'show') + + collapse.toggle() + + expect(spy).toHaveBeenCalled() + }) + + it('should call hide method if show class is present', () => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('.show') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + const spy = spyOn(collapse, 'hide') + + collapse.toggle() + + expect(spy).toHaveBeenCalled() + }) + + it('should find collapse children if they have collapse class too not only data-bs-parent', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' Toggle item 1', + '
    Lorem ipsum 1
    ', + '
    ', + '
    ', + ' Toggle item 2', + '
    Lorem ipsum 2
    ', + '
    ', + '
    ' + ].join('') + + const parent = fixtureEl.querySelector('.my-collapse') + const collapseEl1 = fixtureEl.querySelector('#collapse1') + const collapseEl2 = fixtureEl.querySelector('#collapse2') + + const collapseList = [].concat(...fixtureEl.querySelectorAll('.collapse')) + .map(el => new Collapse(el, { + parent, + toggle: false + })) + + collapseEl2.addEventListener('shown.bs.collapse', () => { + expect(collapseEl2).toHaveClass('show') + expect(collapseEl1).not.toHaveClass('show') + resolve() + }) + + collapseList[1].toggle() + }) + }) + }) + + describe('show', () => { + it('should do nothing if is transitioning', () => { + fixtureEl.innerHTML = '
    ' + + const spy = spyOn(EventHandler, 'trigger') + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapse._isTransitioning = true + collapse.show() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should do nothing if already shown', () => { + fixtureEl.innerHTML = '
    ' + + const spy = spyOn(EventHandler, 'trigger') + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapse.show() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should show a collapsed element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapseEl.addEventListener('show.bs.collapse', () => { + expect(collapseEl.style.height).toEqual('0px') + }) + collapseEl.addEventListener('shown.bs.collapse', () => { + expect(collapseEl).toHaveClass('show') + expect(collapseEl.style.height).toEqual('') + resolve() + }) + + collapse.show() + }) + }) + + it('should show a collapsed element on width', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapseEl.addEventListener('show.bs.collapse', () => { + expect(collapseEl.style.width).toEqual('0px') + }) + collapseEl.addEventListener('shown.bs.collapse', () => { + expect(collapseEl).toHaveClass('show') + expect(collapseEl.style.width).toEqual('') + resolve() + }) + + collapse.show() + }) + }) + + it('should collapse only the first collapse', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const el1 = fixtureEl.querySelector('#collapse1') + const el2 = fixtureEl.querySelector('#collapse2') + const collapse = new Collapse(el1, { + toggle: false + }) + + el1.addEventListener('shown.bs.collapse', () => { + expect(el1).toHaveClass('show') + expect(el2).toHaveClass('show') + resolve() + }) + + collapse.show() + }) + }) + + it('should be able to handle toggling of other children siblings', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    content
    ', + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    content
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const el = selector => fixtureEl.querySelector(selector) + + const parentBtn = el('[data-bs-target="#parentContent"]') + const childBtn1 = el('[data-bs-target="#childContent1"]') + const childBtn2 = el('[data-bs-target="#childContent2"]') + + const parentCollapseEl = el('#parentContent') + const childCollapseEl1 = el('#childContent1') + const childCollapseEl2 = el('#childContent2') + + parentCollapseEl.addEventListener('shown.bs.collapse', () => { + expect(parentCollapseEl).toHaveClass('show') + childBtn1.click() + }) + childCollapseEl1.addEventListener('shown.bs.collapse', () => { + expect(childCollapseEl1).toHaveClass('show') + childBtn2.click() + }) + childCollapseEl2.addEventListener('shown.bs.collapse', () => { + expect(childCollapseEl2).toHaveClass('show') + expect(childCollapseEl1).not.toHaveClass('show') + resolve() + }) + + parentBtn.click() + }) + }) + + it('should not change tab tabpanels descendants on accordion', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '

    ', + ' ', + '

    ', + '
    ', + '
    ', + ' ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const el = fixtureEl.querySelector('#collapseOne') + const activeTabPane = fixtureEl.querySelector('#nav-home') + const collapse = new Collapse(el) + let times = 1 + + el.addEventListener('hidden.bs.collapse', () => { + collapse.show() + }) + + el.addEventListener('shown.bs.collapse', () => { + expect(activeTabPane).toHaveClass('show') + times++ + if (times === 2) { + resolve() + } + + collapse.hide() + }) + + collapse.show() + }) + }) + + it('should not fire shown when show is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + const expectEnd = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + } + + collapseEl.addEventListener('show.bs.collapse', event => { + event.preventDefault() + expectEnd() + }) + + collapseEl.addEventListener('shown.bs.collapse', () => { + reject(new Error('should not fire shown event')) + }) + + collapse.show() + }) + }) + }) + + describe('hide', () => { + it('should do nothing if is transitioning', () => { + fixtureEl.innerHTML = '
    ' + + const spy = spyOn(EventHandler, 'trigger') + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapse._isTransitioning = true + collapse.hide() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should do nothing if already shown', () => { + fixtureEl.innerHTML = '
    ' + + const spy = spyOn(EventHandler, 'trigger') + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapse.hide() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should hide a collapsed element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + collapseEl.addEventListener('hidden.bs.collapse', () => { + expect(collapseEl).not.toHaveClass('show') + expect(collapseEl.style.height).toEqual('') + resolve() + }) + + collapse.hide() + }) + }) + + it('should not fire hidden when hide is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + const expectEnd = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + } + + collapseEl.addEventListener('hide.bs.collapse', event => { + event.preventDefault() + expectEnd() + }) + + collapseEl.addEventListener('hidden.bs.collapse', () => { + reject(new Error('should not fire hidden event')) + }) + + collapse.hide() + }) + }) + }) + + describe('dispose', () => { + it('should destroy a collapse', () => { + fixtureEl.innerHTML = '
    ' + + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) + + expect(Collapse.getInstance(collapseEl)).toEqual(collapse) + + collapse.dispose() + + expect(Collapse.getInstance(collapseEl)).toBeNull() + }) + }) + + describe('data-api', () => { + it('should prevent url change if click on nested elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const triggerEl = fixtureEl.querySelector('a') + const nestedTriggerEl = fixtureEl.querySelector('#nested') + + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + triggerEl.addEventListener('click', event => { + expect(event.target.isEqualNode(nestedTriggerEl)).toBeTrue() + expect(event.delegateTarget.isEqualNode(triggerEl)).toBeTrue() + expect(spy).toHaveBeenCalled() + resolve() + }) + + nestedTriggerEl.click() + }) + }) + + it('should show multiple collapsed elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('a') + const collapse1 = fixtureEl.querySelector('#collapse1') + const collapse2 = fixtureEl.querySelector('#collapse2') + + collapse2.addEventListener('shown.bs.collapse', () => { + expect(trigger.getAttribute('aria-expanded')).toEqual('true') + expect(trigger).not.toHaveClass('collapsed') + expect(collapse1).toHaveClass('show') + expect(collapse1).toHaveClass('show') + resolve() + }) + + trigger.click() + }) + }) + + it('should hide multiple collapsed elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('a') + const collapse1 = fixtureEl.querySelector('#collapse1') + const collapse2 = fixtureEl.querySelector('#collapse2') + + collapse2.addEventListener('hidden.bs.collapse', () => { + expect(trigger.getAttribute('aria-expanded')).toEqual('false') + expect(trigger).toHaveClass('collapsed') + expect(collapse1).not.toHaveClass('show') + expect(collapse1).not.toHaveClass('show') + resolve() + }) + + trigger.click() + }) + }) + + it('should remove "collapsed" class from target when collapse is shown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '', + '
    ' + ].join('') + + const link1 = fixtureEl.querySelector('#link1') + const link2 = fixtureEl.querySelector('#link2') + const collapseTest1 = fixtureEl.querySelector('#test1') + + collapseTest1.addEventListener('shown.bs.collapse', () => { + expect(link1.getAttribute('aria-expanded')).toEqual('true') + expect(link2.getAttribute('aria-expanded')).toEqual('true') + expect(link1).not.toHaveClass('collapsed') + expect(link2).not.toHaveClass('collapsed') + resolve() + }) + + link1.click() + }) + }) + + it('should add "collapsed" class to target when collapse is hidden', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '', + '
    ' + ].join('') + + const link1 = fixtureEl.querySelector('#link1') + const link2 = fixtureEl.querySelector('#link2') + const collapseTest1 = fixtureEl.querySelector('#test1') + + collapseTest1.addEventListener('hidden.bs.collapse', () => { + expect(link1.getAttribute('aria-expanded')).toEqual('false') + expect(link2.getAttribute('aria-expanded')).toEqual('false') + expect(link1).toHaveClass('collapsed') + expect(link2).toHaveClass('collapsed') + resolve() + }) + + link1.click() + }) + }) + + it('should allow accordion to use children other than card', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('#linkTrigger') + const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') + const collapseOne = fixtureEl.querySelector('#collapseOne') + const collapseTwo = fixtureEl.querySelector('#collapseTwo') + + collapseOne.addEventListener('shown.bs.collapse', () => { + expect(collapseOne).toHaveClass('show') + expect(collapseTwo).not.toHaveClass('show') + + collapseTwo.addEventListener('shown.bs.collapse', () => { + expect(collapseOne).not.toHaveClass('show') + expect(collapseTwo).toHaveClass('show') + resolve() + }) + + triggerTwo.click() + }) + + trigger.click() + }) + }) + + it('should not prevent event for input', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const target = fixtureEl.querySelector('input') + const collapseEl = fixtureEl.querySelector('#collapsediv1') + + collapseEl.addEventListener('shown.bs.collapse', () => { + expect(collapseEl).toHaveClass('show') + expect(target.checked).toBeTrue() + resolve() + }) + + target.click() + }) + }) + + it('should allow accordion to contain nested elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const triggerEl = fixtureEl.querySelector('#linkTrigger') + const triggerTwoEl = fixtureEl.querySelector('#linkTriggerTwo') + const collapseOneEl = fixtureEl.querySelector('#collapseOne') + const collapseTwoEl = fixtureEl.querySelector('#collapseTwo') + + collapseOneEl.addEventListener('shown.bs.collapse', () => { + expect(collapseOneEl).toHaveClass('show') + expect(triggerEl).not.toHaveClass('collapsed') + expect(triggerEl.getAttribute('aria-expanded')).toEqual('true') + + expect(collapseTwoEl).not.toHaveClass('show') + expect(triggerTwoEl).toHaveClass('collapsed') + expect(triggerTwoEl.getAttribute('aria-expanded')).toEqual('false') + + collapseTwoEl.addEventListener('shown.bs.collapse', () => { + expect(collapseOneEl).not.toHaveClass('show') + expect(triggerEl).toHaveClass('collapsed') + expect(triggerEl.getAttribute('aria-expanded')).toEqual('false') + + expect(collapseTwoEl).toHaveClass('show') + expect(triggerTwoEl).not.toHaveClass('collapsed') + expect(triggerTwoEl.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + triggerTwoEl.click() + }) + + triggerEl.click() + }) + }) + + it('should allow accordion to target multiple elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('#linkTriggerOne') + const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') + const collapseOneOne = fixtureEl.querySelector('#collapseOneOne') + const collapseOneTwo = fixtureEl.querySelector('#collapseOneTwo') + const collapseTwoOne = fixtureEl.querySelector('#collapseTwoOne') + const collapseTwoTwo = fixtureEl.querySelector('#collapseTwoTwo') + const collapsedElements = { + one: false, + two: false + } + + function firstTest() { + expect(collapseOneOne).toHaveClass('show') + expect(collapseOneTwo).toHaveClass('show') + + expect(collapseTwoOne).not.toHaveClass('show') + expect(collapseTwoTwo).not.toHaveClass('show') + + triggerTwo.click() + } + + function secondTest() { + expect(collapseOneOne).not.toHaveClass('show') + expect(collapseOneTwo).not.toHaveClass('show') + + expect(collapseTwoOne).toHaveClass('show') + expect(collapseTwoTwo).toHaveClass('show') + resolve() + } + + collapseOneOne.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.one) { + firstTest() + } else { + collapsedElements.one = true + } + }) + + collapseOneTwo.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.one) { + firstTest() + } else { + collapsedElements.one = true + } + }) + + collapseTwoOne.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.two) { + secondTest() + } else { + collapsedElements.two = true + } + }) + + collapseTwoTwo.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.two) { + secondTest() + } else { + collapsedElements.two = true + } + }) + + trigger.click() + }) + }) + + it('should collapse accordion children but not nested accordion children', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('#linkTrigger') + const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') + const nestedTrigger = fixtureEl.querySelector('#nestedLinkTrigger') + const collapseOne = fixtureEl.querySelector('#collapseOne') + const collapseTwo = fixtureEl.querySelector('#collapseTwo') + const nestedCollapseOne = fixtureEl.querySelector('#nestedCollapseOne') + + function handlerCollapseOne() { + expect(collapseOne).toHaveClass('show') + expect(collapseTwo).not.toHaveClass('show') + expect(nestedCollapseOne).not.toHaveClass('show') + + nestedCollapseOne.addEventListener('shown.bs.collapse', handlerNestedCollapseOne) + nestedTrigger.click() + collapseOne.removeEventListener('shown.bs.collapse', handlerCollapseOne) + } + + function handlerNestedCollapseOne() { + expect(collapseOne).toHaveClass('show') + expect(collapseTwo).not.toHaveClass('show') + expect(nestedCollapseOne).toHaveClass('show') + + collapseTwo.addEventListener('shown.bs.collapse', () => { + expect(collapseOne).not.toHaveClass('show') + expect(collapseTwo).toHaveClass('show') + expect(nestedCollapseOne).toHaveClass('show') + resolve() + }) + + triggerTwo.click() + nestedCollapseOne.removeEventListener('shown.bs.collapse', handlerNestedCollapseOne) + } + + collapseOne.addEventListener('shown.bs.collapse', handlerCollapseOne) + trigger.click() + }) + }) + + it('should add "collapsed" class and set aria-expanded to triggers only when all the targeted collapse are hidden', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '', + '', + '
    ', + '
    ' + ].join('') + + const trigger1 = fixtureEl.querySelector('#trigger1') + const trigger2 = fixtureEl.querySelector('#trigger2') + const trigger3 = fixtureEl.querySelector('#trigger3') + const target1 = fixtureEl.querySelector('#test1') + const target2 = fixtureEl.querySelector(`#${CSS.escape('0/my/id')}`) + + const target2Shown = () => { + expect(trigger1).not.toHaveClass('collapsed') + expect(trigger1.getAttribute('aria-expanded')).toEqual('true') + + expect(trigger2).not.toHaveClass('collapsed') + expect(trigger2.getAttribute('aria-expanded')).toEqual('true') + + expect(trigger3).not.toHaveClass('collapsed') + expect(trigger3.getAttribute('aria-expanded')).toEqual('true') + + target2.addEventListener('hidden.bs.collapse', () => { + expect(trigger1).not.toHaveClass('collapsed') + expect(trigger1.getAttribute('aria-expanded')).toEqual('true') + + expect(trigger2).toHaveClass('collapsed') + expect(trigger2.getAttribute('aria-expanded')).toEqual('false') + + expect(trigger3).not.toHaveClass('collapsed') + expect(trigger3.getAttribute('aria-expanded')).toEqual('true') + + target1.addEventListener('hidden.bs.collapse', () => { + expect(trigger1).toHaveClass('collapsed') + expect(trigger1.getAttribute('aria-expanded')).toEqual('false') + + expect(trigger2).toHaveClass('collapsed') + expect(trigger2.getAttribute('aria-expanded')).toEqual('false') + + expect(trigger3).toHaveClass('collapsed') + expect(trigger3.getAttribute('aria-expanded')).toEqual('false') + resolve() + }) + + trigger1.click() + }) + + trigger2.click() + } + + target2.addEventListener('shown.bs.collapse', target2Shown) + trigger3.click() + }) + }) + }) + + describe('jQueryInterface', () => { + it('should create a collapse', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.collapse = Collapse.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.collapse.call(jQueryMock) + + expect(Collapse.getInstance(div)).not.toBeNull() + }) + + it('should not re create a collapse', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const collapse = new Collapse(div) + + jQueryMock.fn.collapse = Collapse.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.collapse.call(jQueryMock) + + expect(Collapse.getInstance(div)).toEqual(collapse) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.collapse = Collapse.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.collapse.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('getInstance', () => { + it('should return collapse instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const collapse = new Collapse(div) + + expect(Collapse.getInstance(div)).toEqual(collapse) + expect(Collapse.getInstance(div)).toBeInstanceOf(Collapse) + }) + + it('should return null when there is no collapse instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Collapse.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return collapse instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const collapse = new Collapse(div) + + expect(Collapse.getOrCreateInstance(div)).toEqual(collapse) + expect(Collapse.getInstance(div)).toEqual(Collapse.getOrCreateInstance(div, {})) + expect(Collapse.getOrCreateInstance(div)).toBeInstanceOf(Collapse) + }) + + it('should return new instance when there is no collapse instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Collapse.getInstance(div)).toBeNull() + expect(Collapse.getOrCreateInstance(div)).toBeInstanceOf(Collapse) + }) + + it('should return new instance when there is no collapse instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Collapse.getInstance(div)).toBeNull() + const collapse = Collapse.getOrCreateInstance(div, { + toggle: false + }) + expect(collapse).toBeInstanceOf(Collapse) + + expect(collapse._config.toggle).toBeFalse() + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const collapse = new Collapse(div, { + toggle: false + }) + expect(Collapse.getInstance(div)).toEqual(collapse) + + const collapse2 = Collapse.getOrCreateInstance(div, { + toggle: true + }) + expect(collapse).toBeInstanceOf(Collapse) + expect(collapse2).toEqual(collapse) + + expect(collapse2._config.toggle).toBeFalse() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/data.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/data.spec.js new file mode 100644 index 00000000..04e57a8b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/data.spec.js @@ -0,0 +1,104 @@ +import Data from '../../../src/dom/data.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +describe('Data', () => { + const TEST_KEY = 'bs.test' + const UNKNOWN_KEY = 'bs.unknown' + const TEST_DATA = { + test: 'bsData' + } + + let fixtureEl + let div + + beforeAll(() => { + fixtureEl = getFixture() + }) + + beforeEach(() => { + fixtureEl.innerHTML = '
    ' + div = fixtureEl.querySelector('div') + }) + + afterEach(() => { + Data.remove(div, TEST_KEY) + clearFixture() + }) + + it('should return null for unknown elements', () => { + const data = { ...TEST_DATA } + + Data.set(div, TEST_KEY, data) + + expect(Data.get(null)).toBeNull() + expect(Data.get(undefined)).toBeNull() + expect(Data.get(document.createElement('div'), TEST_KEY)).toBeNull() + }) + + it('should return null for unknown keys', () => { + const data = { ...TEST_DATA } + + Data.set(div, TEST_KEY, data) + + expect(Data.get(div, null)).toBeNull() + expect(Data.get(div, undefined)).toBeNull() + expect(Data.get(div, UNKNOWN_KEY)).toBeNull() + }) + + it('should store data for an element with a given key and return it', () => { + const data = { ...TEST_DATA } + + Data.set(div, TEST_KEY, data) + + expect(Data.get(div, TEST_KEY)).toEqual(data) + }) + + it('should overwrite data if something is already stored', () => { + const data = { ...TEST_DATA } + const copy = { ...data } + + Data.set(div, TEST_KEY, data) + Data.set(div, TEST_KEY, copy) + + // Using `toBe` since spread creates a shallow copy + expect(Data.get(div, TEST_KEY)).not.toBe(data) + expect(Data.get(div, TEST_KEY)).toBe(copy) + }) + + it('should do nothing when an element has nothing stored', () => { + Data.remove(div, TEST_KEY) + + expect().nothing() + }) + + it('should remove nothing for an unknown key', () => { + const data = { ...TEST_DATA } + + Data.set(div, TEST_KEY, data) + Data.remove(div, UNKNOWN_KEY) + + expect(Data.get(div, TEST_KEY)).toEqual(data) + }) + + it('should remove data for a given key', () => { + const data = { ...TEST_DATA } + + Data.set(div, TEST_KEY, data) + Data.remove(div, TEST_KEY) + + expect(Data.get(div, TEST_KEY)).toBeNull() + }) + + it('should console.error a message if called with multiple keys', () => { + console.error = jasmine.createSpy('console.error') + + const data = { ...TEST_DATA } + const copy = { ...data } + + Data.set(div, TEST_KEY, data) + Data.set(div, UNKNOWN_KEY, copy) + + expect(console.error).toHaveBeenCalled() + expect(Data.get(div, UNKNOWN_KEY)).toBeNull() + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/event-handler.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/event-handler.spec.js new file mode 100644 index 00000000..7f99c412 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/event-handler.spec.js @@ -0,0 +1,480 @@ +import EventHandler from '../../../src/dom/event-handler.js' +import { noop } from '../../../src/util/index.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +describe('EventHandler', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('on', () => { + it('should not add event listener if the event is not a string', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + EventHandler.on(div, null, noop) + EventHandler.on(null, 'click', noop) + + expect().nothing() + }) + + it('should add event listener', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + EventHandler.on(div, 'click', () => { + expect().nothing() + resolve() + }) + + div.click() + }) + }) + + it('should add namespaced event listener', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + EventHandler.on(div, 'bs.namespace', () => { + expect().nothing() + resolve() + }) + + EventHandler.trigger(div, 'bs.namespace') + }) + }) + + it('should add native namespaced event listener', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + EventHandler.on(div, 'click.namespace', () => { + expect().nothing() + resolve() + }) + + EventHandler.trigger(div, 'click') + }) + }) + + it('should handle event delegation', () => { + return new Promise(resolve => { + EventHandler.on(document, 'click', '.test', () => { + expect().nothing() + resolve() + }) + + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + div.click() + }) + }) + + it('should handle mouseenter/mouseleave like the native counterpart', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const outer = fixtureEl.querySelector('.outer') + const inner = fixtureEl.querySelector('.inner') + const nested = fixtureEl.querySelector('.nested') + const deep = fixtureEl.querySelector('.deep') + const sibling = fixtureEl.querySelector('.sibling') + + const enterSpy = jasmine.createSpy('mouseenter') + const leaveSpy = jasmine.createSpy('mouseleave') + const delegateEnterSpy = jasmine.createSpy('mouseenter') + const delegateLeaveSpy = jasmine.createSpy('mouseleave') + + EventHandler.on(inner, 'mouseenter', enterSpy) + EventHandler.on(inner, 'mouseleave', leaveSpy) + EventHandler.on(outer, 'mouseenter', '.inner', delegateEnterSpy) + EventHandler.on(outer, 'mouseleave', '.inner', delegateLeaveSpy) + + EventHandler.on(sibling, 'mouseenter', () => { + expect(enterSpy.calls.count()).toEqual(2) + expect(leaveSpy.calls.count()).toEqual(2) + expect(delegateEnterSpy.calls.count()).toEqual(2) + expect(delegateLeaveSpy.calls.count()).toEqual(2) + resolve() + }) + + const moveMouse = (from, to) => { + from.dispatchEvent(new MouseEvent('mouseout', { + bubbles: true, + relatedTarget: to + })) + + to.dispatchEvent(new MouseEvent('mouseover', { + bubbles: true, + relatedTarget: from + })) + } + + // from outer to deep and back to outer (nested) + moveMouse(outer, inner) + moveMouse(inner, nested) + moveMouse(nested, deep) + moveMouse(deep, nested) + moveMouse(nested, inner) + moveMouse(inner, outer) + + setTimeout(() => { + expect(enterSpy.calls.count()).toEqual(1) + expect(leaveSpy.calls.count()).toEqual(1) + expect(delegateEnterSpy.calls.count()).toEqual(1) + expect(delegateLeaveSpy.calls.count()).toEqual(1) + + // from outer to inner to sibling (adjacent) + moveMouse(outer, inner) + moveMouse(inner, sibling) + }, 20) + }) + }) + }) + + describe('one', () => { + it('should call listener just once', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + let called = 0 + const div = fixtureEl.querySelector('div') + const obj = { + oneListener() { + called++ + } + } + + EventHandler.one(div, 'bootstrap', obj.oneListener) + + EventHandler.trigger(div, 'bootstrap') + EventHandler.trigger(div, 'bootstrap') + + setTimeout(() => { + expect(called).toEqual(1) + resolve() + }, 20) + }) + }) + + it('should call delegated listener just once', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + let called = 0 + const div = fixtureEl.querySelector('div') + const obj = { + oneListener() { + called++ + } + } + + EventHandler.one(fixtureEl, 'bootstrap', 'div', obj.oneListener) + + EventHandler.trigger(div, 'bootstrap') + EventHandler.trigger(div, 'bootstrap') + + setTimeout(() => { + expect(called).toEqual(1) + resolve() + }, 20) + }) + }) + }) + + describe('off', () => { + it('should not remove a listener', () => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + EventHandler.off(div, null, noop) + EventHandler.off(null, 'click', noop) + expect().nothing() + }) + + it('should remove a listener', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + let called = 0 + const handler = () => { + called++ + } + + EventHandler.on(div, 'foobar', handler) + EventHandler.trigger(div, 'foobar') + + EventHandler.off(div, 'foobar', handler) + EventHandler.trigger(div, 'foobar') + + setTimeout(() => { + expect(called).toEqual(1) + resolve() + }, 20) + }) + }) + + it('should remove all the events', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + let called = 0 + + EventHandler.on(div, 'foobar', () => { + called++ + }) + EventHandler.on(div, 'foobar', () => { + called++ + }) + EventHandler.trigger(div, 'foobar') + + EventHandler.off(div, 'foobar') + EventHandler.trigger(div, 'foobar') + + setTimeout(() => { + expect(called).toEqual(2) + resolve() + }, 20) + }) + }) + + it('should remove all the namespaced listeners if namespace is passed', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + let called = 0 + + EventHandler.on(div, 'foobar.namespace', () => { + called++ + }) + EventHandler.on(div, 'foofoo.namespace', () => { + called++ + }) + EventHandler.trigger(div, 'foobar.namespace') + EventHandler.trigger(div, 'foofoo.namespace') + + EventHandler.off(div, '.namespace') + EventHandler.trigger(div, 'foobar.namespace') + EventHandler.trigger(div, 'foofoo.namespace') + + setTimeout(() => { + expect(called).toEqual(2) + resolve() + }, 20) + }) + }) + + it('should remove the namespaced listeners', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + let calledCallback1 = 0 + let calledCallback2 = 0 + + EventHandler.on(div, 'foobar.namespace', () => { + calledCallback1++ + }) + EventHandler.on(div, 'foofoo.namespace', () => { + calledCallback2++ + }) + + EventHandler.trigger(div, 'foobar.namespace') + EventHandler.off(div, 'foobar.namespace') + EventHandler.trigger(div, 'foobar.namespace') + + EventHandler.trigger(div, 'foofoo.namespace') + + setTimeout(() => { + expect(calledCallback1).toEqual(1) + expect(calledCallback2).toEqual(1) + resolve() + }, 20) + }) + }) + + it('should remove the all the namespaced listeners for native events', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + let called = 0 + + EventHandler.on(div, 'click.namespace', () => { + called++ + }) + EventHandler.on(div, 'click.namespace2', () => { + called++ + }) + + EventHandler.trigger(div, 'click') + EventHandler.off(div, 'click') + EventHandler.trigger(div, 'click') + + setTimeout(() => { + expect(called).toEqual(2) + resolve() + }, 20) + }) + }) + + it('should remove the specified namespaced listeners for native events', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const div = fixtureEl.querySelector('div') + + let called1 = 0 + let called2 = 0 + + EventHandler.on(div, 'click.namespace', () => { + called1++ + }) + EventHandler.on(div, 'click.namespace2', () => { + called2++ + }) + EventHandler.trigger(div, 'click') + + EventHandler.off(div, 'click.namespace') + EventHandler.trigger(div, 'click') + + setTimeout(() => { + expect(called1).toEqual(1) + expect(called2).toEqual(2) + resolve() + }, 20) + }) + }) + + it('should remove a listener registered by .one', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const handler = () => { + reject(new Error('called')) + } + + EventHandler.one(div, 'foobar', handler) + EventHandler.off(div, 'foobar', handler) + + EventHandler.trigger(div, 'foobar') + setTimeout(() => { + expect().nothing() + resolve() + }, 20) + }) + }) + + it('should remove the correct delegated event listener', () => { + const element = document.createElement('div') + const subelement = document.createElement('span') + element.append(subelement) + + const anchor = document.createElement('a') + element.append(anchor) + + let i = 0 + const handler = () => { + i++ + } + + EventHandler.on(element, 'click', 'a', handler) + EventHandler.on(element, 'click', 'span', handler) + + fixtureEl.append(element) + + EventHandler.trigger(anchor, 'click') + EventHandler.trigger(subelement, 'click') + + // first listeners called + expect(i).toEqual(2) + + EventHandler.off(element, 'click', 'span', handler) + EventHandler.trigger(subelement, 'click') + + // removed listener not called + expect(i).toEqual(2) + + EventHandler.trigger(anchor, 'click') + + // not removed listener called + expect(i).toEqual(3) + + EventHandler.on(element, 'click', 'span', handler) + EventHandler.trigger(anchor, 'click') + EventHandler.trigger(subelement, 'click') + + // listener re-registered + expect(i).toEqual(5) + + EventHandler.off(element, 'click', 'span') + EventHandler.trigger(subelement, 'click') + + // listener removed again + expect(i).toEqual(5) + }) + }) + + describe('general functionality', () => { + it('should hydrate properties, and make them configurable', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const div1 = fixtureEl.querySelector('#div1') + const div2 = fixtureEl.querySelector('#div2') + + EventHandler.on(div1, 'click', event => { + expect(event.currentTarget).toBe(div2) + expect(event.delegateTarget).toBe(div1) + expect(event.originalTarget).toBeNull() + + Object.defineProperty(event, 'currentTarget', { + configurable: true, + get() { + return div1 + } + }) + + expect(event.currentTarget).toBe(div1) + resolve() + }) + + expect(() => { + EventHandler.trigger(div1, 'click', { originalTarget: null, currentTarget: div2 }) + }).not.toThrowError(TypeError) + }) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/manipulator.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/manipulator.spec.js new file mode 100644 index 00000000..9d0be321 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/manipulator.spec.js @@ -0,0 +1,135 @@ +import Manipulator from '../../../src/dom/manipulator.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +describe('Manipulator', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('setDataAttribute', () => { + it('should set data attribute prefixed with bs', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + Manipulator.setDataAttribute(div, 'key', 'value') + expect(div.getAttribute('data-bs-key')).toEqual('value') + }) + + it('should set data attribute in kebab case', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + Manipulator.setDataAttribute(div, 'testKey', 'value') + expect(div.getAttribute('data-bs-test-key')).toEqual('value') + }) + }) + + describe('removeDataAttribute', () => { + it('should only remove bs-prefixed data attribute', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + Manipulator.removeDataAttribute(div, 'key') + expect(div.getAttribute('data-bs-key')).toBeNull() + expect(div.getAttribute('data-key-bs')).toEqual('postfixed') + expect(div.getAttribute('data-key')).toEqual('value') + }) + + it('should remove data attribute in kebab case', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + Manipulator.removeDataAttribute(div, 'testKey') + expect(div.getAttribute('data-bs-test-key')).toBeNull() + }) + }) + + describe('getDataAttributes', () => { + it('should return an empty object for null', () => { + expect(Manipulator.getDataAttributes(null)).toEqual({}) + expect().nothing() + }) + + it('should get only bs-prefixed data attributes without bs namespace', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Manipulator.getDataAttributes(div)).toEqual({ + toggle: 'tabs', + target: '#element' + }) + }) + + it('should omit `bs-config` data attribute', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Manipulator.getDataAttributes(div)).toEqual({ + toggle: 'tabs', + target: '#element' + }) + }) + }) + + describe('getDataAttribute', () => { + it('should only get bs-prefixed data attribute', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Manipulator.getDataAttribute(div, 'key')).toEqual('value') + expect(Manipulator.getDataAttribute(div, 'test')).toBeNull() + expect(Manipulator.getDataAttribute(div, 'toggle')).toBeNull() + }) + + it('should get data attribute in kebab case', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Manipulator.getDataAttribute(div, 'testKey')).toEqual('value') + }) + + it('should normalize data', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Manipulator.getDataAttribute(div, 'test')).toBeFalse() + + div.setAttribute('data-bs-test', 'true') + expect(Manipulator.getDataAttribute(div, 'test')).toBeTrue() + + div.setAttribute('data-bs-test', '1') + expect(Manipulator.getDataAttribute(div, 'test')).toEqual(1) + }) + + it('should normalize json data', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Manipulator.getDataAttribute(div, 'test')).toEqual({ delay: { show: 100, hide: 10 } }) + + const objectData = { 'Super Hero': ['Iron Man', 'Super Man'], testNum: 90, url: 'http://localhost:8080/test?foo=bar' } + const dataStr = JSON.stringify(objectData) + div.setAttribute('data-bs-test', encodeURIComponent(dataStr)) + expect(Manipulator.getDataAttribute(div, 'test')).toEqual(objectData) + + div.setAttribute('data-bs-test', dataStr) + expect(Manipulator.getDataAttribute(div, 'test')).toEqual(objectData) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/selector-engine.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/selector-engine.spec.js new file mode 100644 index 00000000..95d9bf8e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dom/selector-engine.spec.js @@ -0,0 +1,414 @@ +import SelectorEngine from '../../../src/dom/selector-engine.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +describe('SelectorEngine', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('find', () => { + it('should find elements', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(SelectorEngine.find('div', fixtureEl)).toEqual([div]) + }) + + it('should find elements globally', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('#test') + + expect(SelectorEngine.find('#test')).toEqual([div]) + }) + + it('should handle :scope selectors', () => { + fixtureEl.innerHTML = [ + '
      ', + '
    • ', + '
    • ', + ' link', + '
    • ', + '
    • ', + '
    ' + ].join('') + + const listEl = fixtureEl.querySelector('ul') + const aActive = fixtureEl.querySelector('.active') + + expect(SelectorEngine.find(':scope > li > .active', listEl)).toEqual([aActive]) + }) + }) + + describe('findOne', () => { + it('should return one element', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('#test') + + expect(SelectorEngine.findOne('#test')).toEqual(div) + }) + }) + + describe('children', () => { + it('should find children', () => { + fixtureEl.innerHTML = [ + '
      ', + '
    • ', + '
    • ', + '
    • ', + '
    ' + ].join('') + + const list = fixtureEl.querySelector('ul') + const liList = [].concat(...fixtureEl.querySelectorAll('li')) + const result = SelectorEngine.children(list, 'li') + + expect(result).toEqual(liList) + }) + }) + + describe('parents', () => { + it('should return parents', () => { + expect(SelectorEngine.parents(fixtureEl, 'body')).toHaveSize(1) + }) + }) + + describe('prev', () => { + it('should return previous element', () => { + fixtureEl.innerHTML = '
    ' + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelector('.test') + + expect(SelectorEngine.prev(btn, '.test')).toEqual([divTest]) + }) + + it('should return previous element with an extra element between', () => { + fixtureEl.innerHTML = [ + '
    ', + '', + '' + ].join('') + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelector('.test') + + expect(SelectorEngine.prev(btn, '.test')).toEqual([divTest]) + }) + + it('should return previous element with comments or text nodes between', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '', + 'Text', + '' + ].join('') + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelectorAll('.test')[1] + + expect(SelectorEngine.prev(btn, '.test')).toEqual([divTest]) + }) + }) + + describe('next', () => { + it('should return next element', () => { + fixtureEl.innerHTML = '
    ' + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelector('.test') + + expect(SelectorEngine.next(divTest, '.btn')).toEqual([btn]) + }) + + it('should return next element with an extra element between', () => { + fixtureEl.innerHTML = [ + '
    ', + '', + '' + ].join('') + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelector('.test') + + expect(SelectorEngine.next(divTest, '.btn')).toEqual([btn]) + }) + + it('should return next element with comments or text nodes between', () => { + fixtureEl.innerHTML = [ + '
    ', + '', + 'Text', + '', + '' + ].join('') + + const btn = fixtureEl.querySelector('.btn') + const divTest = fixtureEl.querySelector('.test') + + expect(SelectorEngine.next(divTest, '.btn')).toEqual([btn]) + }) + }) + + describe('focusableChildren', () => { + it('should return only elements with specific tag names', () => { + fixtureEl.innerHTML = [ + '
    lorem
    ', + 'lorem', + 'lorem', + '', + '', + '', + '', + '
    lorem
    ' + ].join('') + + const expectedElements = [ + fixtureEl.querySelector('a'), + fixtureEl.querySelector('button'), + fixtureEl.querySelector('input'), + fixtureEl.querySelector('textarea'), + fixtureEl.querySelector('select'), + fixtureEl.querySelector('details') + ] + + expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements) + }) + + it('should return any element with non negative tab index', () => { + fixtureEl.innerHTML = [ + '
    lorem
    ', + '
    lorem
    ', + '
    lorem
    ' + ].join('') + + const expectedElements = [ + fixtureEl.querySelector('[tabindex]'), + fixtureEl.querySelector('[tabindex="0"]'), + fixtureEl.querySelector('[tabindex="10"]') + ] + + expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements) + }) + + it('should return not return elements with negative tab index', () => { + fixtureEl.innerHTML = '' + + const expectedElements = [] + + expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements) + }) + + it('should return contenteditable elements', () => { + fixtureEl.innerHTML = '
    lorem
    ' + + const expectedElements = [fixtureEl.querySelector('[contenteditable="true"]')] + + expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements) + }) + + it('should not return disabled elements', () => { + fixtureEl.innerHTML = '' + + const expectedElements = [] + + expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements) + }) + + it('should not return invisible elements', () => { + fixtureEl.innerHTML = '' + + const expectedElements = [] + + expect(SelectorEngine.focusableChildren(fixtureEl)).toEqual(expectedElements) + }) + }) + + describe('getSelectorFromElement', () => { + it('should get selector from data-bs-target', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('.target') + }) + + it('should get selector from href if no data-bs-target set', () => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('.target') + }) + + it('should get selector from href if data-bs-target equal to #', () => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('.target') + }) + + it('should return null if a selector from a href is a url without an anchor', () => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toBeNull() + }) + + it('should return the anchor if a selector from a href is a url', () => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toEqual('#target') + }) + + it('should return null if selector not found', () => { + fixtureEl.innerHTML = '' + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toBeNull() + }) + + it('should return null if no selector', () => { + fixtureEl.innerHTML = '
    ' + + const testEl = fixtureEl.querySelector('div') + + expect(SelectorEngine.getSelectorFromElement(testEl)).toBeNull() + }) + }) + + describe('getElementFromSelector', () => { + it('should get element from data-bs-target', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target')) + }) + + it('should get element from href if no data-bs-target set', () => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target')) + }) + + it('should return null if element not found', () => { + fixtureEl.innerHTML = '' + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getElementFromSelector(testEl)).toBeNull() + }) + + it('should return null if no selector', () => { + fixtureEl.innerHTML = '
    ' + + const testEl = fixtureEl.querySelector('div') + + expect(SelectorEngine.getElementFromSelector(testEl)).toBeNull() + }) + }) + + describe('getMultipleElementsFromSelector', () => { + it('should get elements from data-bs-target', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target'))) + }) + + it('should get elements if several ids are given', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target'))) + }) + + it('should get elements if several ids with special chars are given', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target'))) + }) + + it('should get elements in array, from href if no data-bs-target set', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target'))) + }) + + it('should return empty array if elements not found', () => { + fixtureEl.innerHTML = '' + + const testEl = fixtureEl.querySelector('#test') + + expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toHaveSize(0) + }) + + it('should return empty array if no selector', () => { + fixtureEl.innerHTML = '
    ' + + const testEl = fixtureEl.querySelector('div') + + expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toHaveSize(0) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dropdown.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dropdown.spec.js new file mode 100644 index 00000000..63ae4bd1 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/dropdown.spec.js @@ -0,0 +1,2436 @@ +import EventHandler from '../../src/dom/event-handler.js' +import Dropdown from '../../src/dropdown.js' +import { noop } from '../../src/util/index.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Dropdown', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Dropdown.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Dropdown.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DefaultType', () => { + it('should return plugin default type config', () => { + expect(Dropdown.DefaultType).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Dropdown.DATA_KEY).toEqual('bs.dropdown') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownBySelector = new Dropdown('[data-bs-toggle="dropdown"]') + const dropdownByElement = new Dropdown(btnDropdown) + + expect(dropdownBySelector._element).toEqual(btnDropdown) + expect(dropdownByElement._element).toEqual(btnDropdown) + }) + + it('should work on invalid markup', () => { + return new Promise(resolve => { + // TODO: REMOVE in v6 + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownElem = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(dropdownElem) + + dropdownElem.addEventListener('shown.bs.dropdown', () => { + resolve() + }) + + expect().nothing() + dropdown.show() + }) + }) + + it('should create offset modifier correctly when offset option is a function', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const getOffset = jasmine.createSpy('getOffset').and.returnValue([10, 20]) + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown, { + offset: getOffset, + popperConfig: { + onFirstUpdate(state) { + expect(getOffset).toHaveBeenCalledWith({ + popper: state.rects.popper, + reference: state.rects.reference, + placement: state.placement + }, btnDropdown) + resolve() + } + } + }) + const offset = dropdown._getOffset() + + expect(typeof offset).toEqual('function') + + dropdown.show() + }) + }) + + it('should create offset modifier correctly when offset option is a string into data attribute', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + expect(dropdown._getOffset()).toEqual([10, 20]) + }) + + it('should allow to pass config to Popper with `popperConfig`', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown, { + popperConfig: { + placement: 'left' + } + }) + + const popperConfig = dropdown._getPopperConfig() + + expect(popperConfig.placement).toEqual('left') + }) + + it('should allow to pass config to Popper with `popperConfig` as a function', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const getPopperConfig = jasmine.createSpy('getPopperConfig').and.returnValue({ placement: 'left' }) + const dropdown = new Dropdown(btnDropdown, { + popperConfig: getPopperConfig + }) + + const popperConfig = dropdown._getPopperConfig() + + // Ensure that the function was called with the default config. + expect(getPopperConfig).toHaveBeenCalledWith(jasmine.objectContaining({ + placement: jasmine.any(String) + })) + expect(popperConfig.placement).toEqual('left') + }) + }) + + describe('toggle', () => { + it('should toggle a dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should destroy old popper references on toggle', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const btnDropdown1 = fixtureEl.querySelector('.firstBtn') + const btnDropdown2 = fixtureEl.querySelector('.secondBtn') + const firstDropdownEl = fixtureEl.querySelector('.first') + const secondDropdownEl = fixtureEl.querySelector('.second') + const dropdown1 = new Dropdown(btnDropdown1) + + firstDropdownEl.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown1).toHaveClass('show') + spyOn(dropdown1._popper, 'destroy') + btnDropdown2.click() + }) + + secondDropdownEl.addEventListener('shown.bs.dropdown', () => setTimeout(() => { + expect(dropdown1._popper.destroy).toHaveBeenCalled() + resolve() + })) + + dropdown1.toggle() + }) + }) + + it('should toggle a dropdown and add/remove event listener on mobile', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const defaultValueOnTouchStart = document.documentElement.ontouchstart + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + document.documentElement.ontouchstart = noop + const spy = spyOn(EventHandler, 'on') + const spyOff = spyOn(EventHandler, 'off') + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + expect(spy).toHaveBeenCalledWith(jasmine.any(Object), 'mouseover', noop) + + dropdown.toggle() + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(btnDropdown).not.toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('false') + expect(spyOff).toHaveBeenCalledWith(jasmine.any(Object), 'mouseover', noop) + + document.documentElement.ontouchstart = defaultValueOnTouchStart + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropdown at the right', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a centered dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropup', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropupEl = fixtureEl.querySelector('.dropup') + const dropdown = new Dropdown(btnDropdown) + + dropupEl.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropup centered', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropupEl = fixtureEl.querySelector('.dropup-center') + const dropdown = new Dropdown(btnDropdown) + + dropupEl.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropup at the right', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropupEl = fixtureEl.querySelector('.dropup') + const dropdown = new Dropdown(btnDropdown) + + dropupEl.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropend', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropendEl = fixtureEl.querySelector('.dropend') + const dropdown = new Dropdown(btnDropdown) + + dropendEl.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropstart', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropstartEl = fixtureEl.querySelector('.dropstart') + const dropdown = new Dropdown(btnDropdown) + + dropstartEl.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropdown with parent reference', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown, { + reference: 'parent' + }) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropdown with a dom node reference', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown, { + reference: fixtureEl + }) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropdown with a jquery object reference', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown, { + reference: { 0: fixtureEl, jquery: 'jQuery' } + }) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) + + dropdown.toggle() + }) + }) + + it('should toggle a dropdown with a valid virtual element reference', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const virtualElement = { + nodeType: 1, + getBoundingClientRect() { + return { + width: 0, + height: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } + } + + expect(() => new Dropdown(btnDropdown, { + reference: {} + })).toThrowError(TypeError, 'DROPDOWN: Option "reference" provided type "object" without a required "getBoundingClientRect" method.') + + expect(() => new Dropdown(btnDropdown, { + reference: { + getBoundingClientRect: 'not-a-function' + } + })).toThrowError(TypeError, 'DROPDOWN: Option "reference" provided type "object" without a required "getBoundingClientRect" method.') + + // use onFirstUpdate as Poppers internal update is executed async + const dropdown = new Dropdown(btnDropdown, { + reference: virtualElement, + popperConfig: { + onFirstUpdate() { + expect(spy).toHaveBeenCalled() + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + } + } + }) + + const spy = spyOn(virtualElement, 'getBoundingClientRect').and.callThrough() + + dropdown.toggle() + }) + }) + + it('should not toggle a dropdown if the element is disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.toggle() + + setTimeout(() => { + expect().nothing() + resolve() + }) + }) + }) + + it('should not toggle a dropdown if the element contains .disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.toggle() + + setTimeout(() => { + expect().nothing() + resolve() + }) + }) + }) + + it('should not toggle a dropdown if the menu is shown', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.toggle() + + setTimeout(() => { + expect().nothing() + resolve() + }) + }) + }) + + it('should not toggle a dropdown if show event is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('show.bs.dropdown', event => { + event.preventDefault() + }) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.toggle() + + setTimeout(() => { + expect().nothing() + resolve() + }) + }) + }) + }) + + describe('show', () => { + it('should show a dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + resolve() + }) + + dropdown.show() + }) + }) + + it('should not show a dropdown if the element is disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.show() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + + it('should not show a dropdown if the element contains .disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.show() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + + it('should not show a dropdown if the menu is shown', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.show() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + + it('should not show a dropdown if show event is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('show.bs.dropdown', event => { + event.preventDefault() + }) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + reject(new Error('should not throw shown.bs.dropdown event')) + }) + + dropdown.show() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + }) + + describe('hide', () => { + it('should hide a dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(dropdownMenu).not.toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('false') + resolve() + }) + + dropdown.hide() + }) + }) + + it('should hide a dropdown and destroy popper', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + spyOn(dropdown._popper, 'destroy') + dropdown.hide() + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(dropdown._popper.destroy).toHaveBeenCalled() + resolve() + }) + + dropdown.show() + }) + }) + + it('should not hide a dropdown if the element is disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + reject(new Error('should not throw hidden.bs.dropdown event')) + }) + + dropdown.hide() + + setTimeout(() => { + expect(dropdownMenu).toHaveClass('show') + resolve() + }, 10) + }) + }) + + it('should not hide a dropdown if the element contains .disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + reject(new Error('should not throw hidden.bs.dropdown event')) + }) + + dropdown.hide() + + setTimeout(() => { + expect(dropdownMenu).toHaveClass('show') + resolve() + }, 10) + }) + }) + + it('should not hide a dropdown if the menu is not shown', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + reject(new Error('should not throw hidden.bs.dropdown event')) + }) + + dropdown.hide() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + + it('should not hide a dropdown if hide event is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('hide.bs.dropdown', event => { + event.preventDefault() + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + reject(new Error('should not throw hidden.bs.dropdown event')) + }) + + dropdown.hide() + + setTimeout(() => { + expect(dropdownMenu).toHaveClass('show') + resolve() + }) + }) + }) + + it('should remove event listener on touch-enabled device that was added in show method', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const defaultValueOnTouchStart = document.documentElement.ontouchstart + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + document.documentElement.ontouchstart = noop + const spy = spyOn(EventHandler, 'off') + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + dropdown.hide() + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(btnDropdown).not.toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('false') + expect(spy).toHaveBeenCalled() + + document.documentElement.ontouchstart = defaultValueOnTouchStart + resolve() + }) + + dropdown.show() + }) + }) + }) + + describe('dispose', () => { + it('should dispose dropdown', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + const dropdown = new Dropdown(btnDropdown) + + expect(dropdown._popper).toBeNull() + expect(dropdown._menu).not.toBeNull() + expect(dropdown._element).not.toBeNull() + const spy = spyOn(EventHandler, 'off') + + dropdown.dispose() + + expect(dropdown._menu).toBeNull() + expect(dropdown._element).toBeNull() + expect(spy).toHaveBeenCalledWith(btnDropdown, Dropdown.EVENT_KEY) + }) + + it('should dispose dropdown with Popper', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + dropdown.toggle() + + expect(dropdown._popper).not.toBeNull() + expect(dropdown._menu).not.toBeNull() + expect(dropdown._element).not.toBeNull() + + dropdown.dispose() + + expect(dropdown._popper).toBeNull() + expect(dropdown._menu).toBeNull() + expect(dropdown._element).toBeNull() + }) + }) + + describe('update', () => { + it('should call Popper and detect navbar on update', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + dropdown.toggle() + + expect(dropdown._popper).not.toBeNull() + + const spyUpdate = spyOn(dropdown._popper, 'update') + const spyDetect = spyOn(dropdown, '_detectNavbar') + + dropdown.update() + + expect(spyUpdate).toHaveBeenCalled() + expect(spyDetect).toHaveBeenCalled() + }) + + it('should just detect navbar on update', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(btnDropdown) + + const spy = spyOn(dropdown, '_detectNavbar') + + dropdown.update() + + expect(dropdown._popper).toBeNull() + expect(spy).toHaveBeenCalled() + }) + }) + + describe('data-api', () => { + it('should show and hide a dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + let showEventTriggered = false + let hideEventTriggered = false + + btnDropdown.addEventListener('show.bs.dropdown', () => { + showEventTriggered = true + }) + + btnDropdown.addEventListener('shown.bs.dropdown', event => setTimeout(() => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + expect(showEventTriggered).toBeTrue() + expect(event.relatedTarget).toEqual(btnDropdown) + document.body.click() + })) + + btnDropdown.addEventListener('hide.bs.dropdown', () => { + hideEventTriggered = true + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', event => { + expect(btnDropdown).not.toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('false') + expect(hideEventTriggered).toBeTrue() + expect(event.relatedTarget).toEqual(btnDropdown) + resolve() + }) + + btnDropdown.click() + }) + }) + + it('should not use "static" Popper in navbar', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(dropdown._popper).not.toBeNull() + expect(dropdownMenu.getAttribute('data-bs-popper')).toEqual('static') + resolve() + }) + + dropdown.show() + }) + }) + + it('should not collapse the dropdown when clicking a select option nested in the dropdown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + const hideSpy = spyOn(dropdown, '_completeHide') + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + const clickEvent = new MouseEvent('click', { + bubbles: true + }) + + dropdownMenu.querySelector('option').dispatchEvent(clickEvent) + }) + + dropdownMenu.addEventListener('click', event => { + expect(event.target.tagName).toMatch(/select|option/i) + + Dropdown.clearMenus(event) + + setTimeout(() => { + expect(hideSpy).not.toHaveBeenCalled() + resolve() + }, 10) + }) + + dropdown.show() + }) + }) + + it('should manage bs attribute `data-bs-popper`="static" when dropdown is in navbar', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(dropdownMenu.getAttribute('data-bs-popper')).toEqual('static') + dropdown.hide() + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(dropdownMenu.getAttribute('data-bs-popper')).toBeNull() + resolve() + }) + + dropdown.show() + }) + }) + + it('should not use Popper if display set to static', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + // Popper adds this attribute when we use it + expect(dropdownMenu.getAttribute('data-popper-placement')).toBeNull() + resolve() + }) + + btnDropdown.click() + }) + }) + + it('should manage bs attribute `data-bs-popper`="static" when display set to static', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const dropdown = new Dropdown(btnDropdown) + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(dropdownMenu.getAttribute('data-bs-popper')).toEqual('static') + dropdown.hide() + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(dropdownMenu.getAttribute('data-bs-popper')).toBeNull() + resolve() + }) + + dropdown.show() + }) + }) + + it('should remove "show" class if tabbing outside of menu', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + btnDropdown.addEventListener('shown.bs.dropdown', () => { + expect(btnDropdown).toHaveClass('show') + + const keyup = createEvent('keyup') + + keyup.key = 'Tab' + document.dispatchEvent(keyup) + }) + + btnDropdown.addEventListener('hidden.bs.dropdown', () => { + expect(btnDropdown).not.toHaveClass('show') + resolve() + }) + + btnDropdown.click() + }) + }) + + it('should remove "show" class if body is clicked, with multiple dropdowns', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + ' ', + ' ', + ' ', + '
    ' + ].join('') + + const triggerDropdownList = fixtureEl.querySelectorAll('[data-bs-toggle="dropdown"]') + + expect(triggerDropdownList).toHaveSize(2) + + const [triggerDropdownFirst, triggerDropdownLast] = triggerDropdownList + + triggerDropdownFirst.addEventListener('shown.bs.dropdown', () => { + expect(triggerDropdownFirst).toHaveClass('show') + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(1) + document.body.click() + }) + + triggerDropdownFirst.addEventListener('hidden.bs.dropdown', () => { + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(0) + triggerDropdownLast.click() + }) + + triggerDropdownLast.addEventListener('shown.bs.dropdown', () => { + expect(triggerDropdownLast).toHaveClass('show') + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(1) + document.body.click() + }) + + triggerDropdownLast.addEventListener('hidden.bs.dropdown', () => { + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(0) + resolve() + }) + + triggerDropdownFirst.click() + }) + }) + + it('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + ' ', + ' ', + ' ', + '
    ' + ].join('') + + const triggerDropdownList = fixtureEl.querySelectorAll('[data-bs-toggle="dropdown"]') + + expect(triggerDropdownList).toHaveSize(2) + + const [triggerDropdownFirst, triggerDropdownLast] = triggerDropdownList + + triggerDropdownFirst.addEventListener('shown.bs.dropdown', () => { + expect(triggerDropdownFirst).toHaveClass('show') + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(1) + + const keyup = createEvent('keyup') + keyup.key = 'Tab' + + document.dispatchEvent(keyup) + }) + + triggerDropdownFirst.addEventListener('hidden.bs.dropdown', () => { + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(0) + triggerDropdownLast.click() + }) + + triggerDropdownLast.addEventListener('shown.bs.dropdown', () => { + expect(triggerDropdownLast).toHaveClass('show') + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(1) + + const keyup = createEvent('keyup') + keyup.key = 'Tab' + + document.dispatchEvent(keyup) + }) + + triggerDropdownLast.addEventListener('hidden.bs.dropdown', () => { + expect(fixtureEl.querySelectorAll('.dropdown-menu.show')).toHaveSize(0) + resolve() + }) + + triggerDropdownFirst.click() + }) + }) + + it('should be able to identify clicked dropdown, even with multiple dropdowns in the same tag', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownToggle1 = fixtureEl.querySelector('#dropdown1') + const dropdownToggle2 = fixtureEl.querySelector('#dropdown2') + const dropdownMenu1 = fixtureEl.querySelector('#menu1') + const dropdownMenu2 = fixtureEl.querySelector('#menu2') + const spy = spyOn(Dropdown, 'getOrCreateInstance').and.callThrough() + + dropdownToggle1.click() + expect(spy).toHaveBeenCalledWith(dropdownToggle1) + + dropdownToggle2.click() + expect(spy).toHaveBeenCalledWith(dropdownToggle2) + + dropdownMenu1.click() + expect(spy).toHaveBeenCalledWith(dropdownToggle1) + + dropdownMenu2.click() + expect(spy).toHaveBeenCalledWith(dropdownToggle2) + }) + + it('should be able to show the proper menu, even with multiple dropdowns in the same tag', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownToggle1 = fixtureEl.querySelector('#dropdown1') + const dropdownToggle2 = fixtureEl.querySelector('#dropdown2') + const dropdownMenu1 = fixtureEl.querySelector('#menu1') + const dropdownMenu2 = fixtureEl.querySelector('#menu2') + + dropdownToggle1.click() + expect(dropdownMenu1).toHaveClass('show') + expect(dropdownMenu2).not.toHaveClass('show') + + dropdownToggle2.click() + expect(dropdownMenu1).not.toHaveClass('show') + expect(dropdownMenu2).toHaveClass('show') + }) + + it('should fire hide and hidden event without a clickEvent if event type is not click', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + triggerDropdown.addEventListener('hide.bs.dropdown', event => { + expect(event.clickEvent).toBeUndefined() + }) + + triggerDropdown.addEventListener('hidden.bs.dropdown', event => { + expect(event.clickEvent).toBeUndefined() + resolve() + }) + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + const keydown = createEvent('keydown') + + keydown.key = 'Escape' + triggerDropdown.dispatchEvent(keydown) + }) + + triggerDropdown.click() + }) + }) + + it('should bubble up the events to the parent elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownParent = fixtureEl.querySelector('.dropdown') + const dropdown = new Dropdown(triggerDropdown) + + const showFunction = jasmine.createSpy('showFunction') + dropdownParent.addEventListener('show.bs.dropdown', showFunction) + + const shownFunction = jasmine.createSpy('shownFunction') + dropdownParent.addEventListener('shown.bs.dropdown', () => { + shownFunction() + dropdown.hide() + }) + + const hideFunction = jasmine.createSpy('hideFunction') + dropdownParent.addEventListener('hide.bs.dropdown', hideFunction) + + dropdownParent.addEventListener('hidden.bs.dropdown', () => { + expect(showFunction).toHaveBeenCalled() + expect(shownFunction).toHaveBeenCalled() + expect(hideFunction).toHaveBeenCalled() + resolve() + }) + + dropdown.show() + }) + }) + + it('should ignore keyboard events within s and ', + ' ', + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const input = fixtureEl.querySelector('input') + const textarea = fixtureEl.querySelector('textarea') + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + input.focus() + const keydown = createEvent('keydown') + + keydown.key = 'ArrowUp' + input.dispatchEvent(keydown) + + expect(document.activeElement).toEqual(input, 'input still focused') + + textarea.focus() + textarea.dispatchEvent(keydown) + + expect(document.activeElement).toEqual(textarea, 'textarea still focused') + resolve() + }) + + triggerDropdown.click() + }) + }) + + it('should skip disabled element when using keyboard navigation', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + const keydown = createEvent('keydown') + keydown.key = 'ArrowDown' + + triggerDropdown.dispatchEvent(keydown) + triggerDropdown.dispatchEvent(keydown) + + expect(document.activeElement).not.toHaveClass('disabled') + expect(document.activeElement.hasAttribute('disabled')).toBeFalse() + resolve() + }) + + triggerDropdown.click() + }) + }) + + it('should skip hidden element when using keyboard navigation', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + const keydown = createEvent('keydown') + keydown.key = 'ArrowDown' + + triggerDropdown.dispatchEvent(keydown) + + expect(document.activeElement).not.toHaveClass('d-none') + expect(document.activeElement.style.display).not.toEqual('none') + expect(document.activeElement.style.visibility).not.toEqual('hidden') + + resolve() + }) + + triggerDropdown.click() + }) + }) + + it('should focus next/previous element when using keyboard navigation', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const item1 = fixtureEl.querySelector('#item1') + const item2 = fixtureEl.querySelector('#item2') + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + const keydownArrowDown = createEvent('keydown') + keydownArrowDown.key = 'ArrowDown' + + triggerDropdown.dispatchEvent(keydownArrowDown) + expect(document.activeElement).toEqual(item1, 'item1 is focused') + + document.activeElement.dispatchEvent(keydownArrowDown) + expect(document.activeElement).toEqual(item2, 'item2 is focused') + + const keydownArrowUp = createEvent('keydown') + keydownArrowUp.key = 'ArrowUp' + + document.activeElement.dispatchEvent(keydownArrowUp) + expect(document.activeElement).toEqual(item1, 'item1 is focused') + + resolve() + }) + + triggerDropdown.click() + }) + }) + + it('should open the dropdown and focus on the last item when using ArrowUp for the first time', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const lastItem = fixtureEl.querySelector('#item2') + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + setTimeout(() => { + expect(document.activeElement).toEqual(lastItem, 'item2 is focused') + resolve() + }) + }) + + const keydown = createEvent('keydown') + keydown.key = 'ArrowUp' + triggerDropdown.dispatchEvent(keydown) + }) + }) + + it('should open the dropdown and focus on the first item when using ArrowDown for the first time', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const firstItem = fixtureEl.querySelector('#item1') + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + setTimeout(() => { + expect(document.activeElement).toEqual(firstItem, 'item1 is focused') + resolve() + }) + }) + + const keydown = createEvent('keydown') + keydown.key = 'ArrowDown' + triggerDropdown.dispatchEvent(keydown) + }) + }) + + it('should not close the dropdown if the user clicks on a text field within dropdown-menu', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const input = fixtureEl.querySelector('input') + + input.addEventListener('click', () => { + expect(triggerDropdown).toHaveClass('show') + resolve() + }) + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + expect(triggerDropdown).toHaveClass('show') + input.dispatchEvent(createEvent('click')) + }) + + triggerDropdown.click() + }) + }) + + it('should not close the dropdown if the user clicks on a textarea within dropdown-menu', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const textarea = fixtureEl.querySelector('textarea') + + textarea.addEventListener('click', () => { + expect(triggerDropdown).toHaveClass('show') + resolve() + }) + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + expect(triggerDropdown).toHaveClass('show') + textarea.dispatchEvent(createEvent('click')) + }) + + triggerDropdown.click() + }) + }) + + it('should close the dropdown if the user clicks on a text field that is not contained within dropdown-menu', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const input = fixtureEl.querySelector('input') + + triggerDropdown.addEventListener('hidden.bs.dropdown', () => { + expect().nothing() + resolve() + }) + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + input.dispatchEvent(createEvent('click', { + bubbles: true + })) + }) + + triggerDropdown.click() + }) + }) + + it('should ignore keyboard events for s and ', + ' ', + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const input = fixtureEl.querySelector('input') + const textarea = fixtureEl.querySelector('textarea') + + const test = (eventKey, elementToDispatch) => { + const event = createEvent('keydown') + event.key = eventKey + elementToDispatch.focus() + elementToDispatch.dispatchEvent(event) + expect(document.activeElement).toEqual(elementToDispatch, `${elementToDispatch.tagName} still focused`) + } + + const keydownEscape = createEvent('keydown') + keydownEscape.key = 'Escape' + + triggerDropdown.addEventListener('shown.bs.dropdown', () => { + // Key Space + test('Space', input) + + test('Space', textarea) + + // Key ArrowUp + test('ArrowUp', input) + + test('ArrowUp', textarea) + + // Key ArrowDown + test('ArrowDown', input) + + test('ArrowDown', textarea) + + // Key Escape + input.focus() + input.dispatchEvent(keydownEscape) + + expect(triggerDropdown).not.toHaveClass('show') + resolve() + }) + + triggerDropdown.click() + }) + }) + + it('should not open dropdown if escape key was pressed on the toggle', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = new Dropdown(triggerDropdown) + const button = fixtureEl.querySelector('button[data-bs-toggle="dropdown"]') + + const spy = spyOn(dropdown, 'toggle') + + // Key escape + button.focus() + // Key escape + const keydownEscape = createEvent('keydown') + keydownEscape.key = 'Escape' + button.dispatchEvent(keydownEscape) + + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + expect(triggerDropdown).not.toHaveClass('show') + resolve() + }, 20) + }) + }) + + it('should propagate escape key events if dropdown is closed', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const parent = fixtureEl.querySelector('.parent') + const toggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + const parentKeyHandler = jasmine.createSpy('parentKeyHandler') + + parent.addEventListener('keydown', parentKeyHandler) + parent.addEventListener('keyup', () => { + expect(parentKeyHandler).toHaveBeenCalled() + resolve() + }) + + const keydownEscape = createEvent('keydown', { bubbles: true }) + keydownEscape.key = 'Escape' + const keyupEscape = createEvent('keyup', { bubbles: true }) + keyupEscape.key = 'Escape' + + toggle.focus() + toggle.dispatchEvent(keydownEscape) + toggle.dispatchEvent(keyupEscape) + }) + }) + + it('should not propagate escape key events if dropdown is open', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const parent = fixtureEl.querySelector('.parent') + const toggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + const parentKeyHandler = jasmine.createSpy('parentKeyHandler') + + parent.addEventListener('keydown', parentKeyHandler) + parent.addEventListener('keyup', () => { + expect(parentKeyHandler).not.toHaveBeenCalled() + resolve() + }) + + const keydownEscape = createEvent('keydown', { bubbles: true }) + keydownEscape.key = 'Escape' + const keyupEscape = createEvent('keyup', { bubbles: true }) + keyupEscape.key = 'Escape' + + toggle.click() + toggle.dispatchEvent(keydownEscape) + toggle.dispatchEvent(keyupEscape) + }) + }) + + it('should close dropdown using `escape` button, and return focus to its trigger', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const toggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + + toggle.addEventListener('shown.bs.dropdown', () => { + const keydownEvent = createEvent('keydown', { bubbles: true }) + keydownEvent.key = 'ArrowDown' + toggle.dispatchEvent(keydownEvent) + keydownEvent.key = 'Escape' + toggle.dispatchEvent(keydownEvent) + }) + + toggle.addEventListener('hidden.bs.dropdown', () => setTimeout(() => { + expect(document.activeElement).toEqual(toggle) + resolve() + })) + + toggle.click() + }) + }) + + it('should close dropdown (only) by clicking inside the dropdown menu when it has data-attribute `data-bs-auto-close="inside"`', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownToggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + + const expectDropdownToBeOpened = () => setTimeout(() => { + expect(dropdownToggle).toHaveClass('show') + dropdownMenu.click() + }, 150) + + dropdownToggle.addEventListener('shown.bs.dropdown', () => { + document.documentElement.click() + expectDropdownToBeOpened() + }) + + dropdownToggle.addEventListener('hidden.bs.dropdown', () => setTimeout(() => { + expect(dropdownToggle).not.toHaveClass('show') + resolve() + })) + + dropdownToggle.click() + }) + }) + + it('should close dropdown (only) by clicking outside the dropdown menu when it has data-attribute `data-bs-auto-close="outside"`', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownToggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + + const expectDropdownToBeOpened = () => setTimeout(() => { + expect(dropdownToggle).toHaveClass('show') + document.documentElement.click() + }, 150) + + dropdownToggle.addEventListener('shown.bs.dropdown', () => { + dropdownMenu.click() + expectDropdownToBeOpened() + }) + + dropdownToggle.addEventListener('hidden.bs.dropdown', () => { + expect(dropdownToggle).not.toHaveClass('show') + resolve() + }) + + dropdownToggle.click() + }) + }) + + it('should not close dropdown by clicking inside or outside the dropdown menu when it has data-attribute `data-bs-auto-close="false"`', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownToggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + + const expectDropdownToBeOpened = (shouldTriggerClick = true) => setTimeout(() => { + expect(dropdownToggle).toHaveClass('show') + if (shouldTriggerClick) { + document.documentElement.click() + } else { + resolve() + } + + expectDropdownToBeOpened(false) + }, 150) + + dropdownToggle.addEventListener('shown.bs.dropdown', () => { + dropdownMenu.click() + expectDropdownToBeOpened() + }) + + dropdownToggle.click() + }) + }) + + it('should be able to identify clicked dropdown, no matter the markup order', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropdownToggle = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdownMenu = fixtureEl.querySelector('.dropdown-menu') + const spy = spyOn(Dropdown, 'getOrCreateInstance').and.callThrough() + + dropdownToggle.click() + expect(spy).toHaveBeenCalledWith(dropdownToggle) + dropdownMenu.click() + expect(spy).toHaveBeenCalledWith(dropdownToggle) + }) + }) + + describe('jQueryInterface', () => { + it('should create a dropdown', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.dropdown = Dropdown.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.dropdown.call(jQueryMock) + + expect(Dropdown.getInstance(div)).not.toBeNull() + }) + + it('should not re create a dropdown', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const dropdown = new Dropdown(div) + + jQueryMock.fn.dropdown = Dropdown.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.dropdown.call(jQueryMock) + + expect(Dropdown.getInstance(div)).toEqual(dropdown) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.dropdown = Dropdown.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.dropdown.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('getInstance', () => { + it('should return dropdown instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const dropdown = new Dropdown(div) + + expect(Dropdown.getInstance(div)).toEqual(dropdown) + expect(Dropdown.getInstance(div)).toBeInstanceOf(Dropdown) + }) + + it('should return null when there is no dropdown instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Dropdown.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return dropdown instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const dropdown = new Dropdown(div) + + expect(Dropdown.getOrCreateInstance(div)).toEqual(dropdown) + expect(Dropdown.getInstance(div)).toEqual(Dropdown.getOrCreateInstance(div, {})) + expect(Dropdown.getOrCreateInstance(div)).toBeInstanceOf(Dropdown) + }) + + it('should return new instance when there is no dropdown instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Dropdown.getInstance(div)).toBeNull() + expect(Dropdown.getOrCreateInstance(div)).toBeInstanceOf(Dropdown) + }) + + it('should return new instance when there is no dropdown instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Dropdown.getInstance(div)).toBeNull() + const dropdown = Dropdown.getOrCreateInstance(div, { + display: 'dynamic' + }) + expect(dropdown).toBeInstanceOf(Dropdown) + + expect(dropdown._config.display).toEqual('dynamic') + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const dropdown = new Dropdown(div, { + display: 'dynamic' + }) + expect(Dropdown.getInstance(div)).toEqual(dropdown) + + const dropdown2 = Dropdown.getOrCreateInstance(div, { + display: 'static' + }) + expect(dropdown).toBeInstanceOf(Dropdown) + expect(dropdown2).toEqual(dropdown) + + expect(dropdown2._config.display).toEqual('dynamic') + }) + }) + + it('should open dropdown when pressing keydown or keyup', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const dropdown = fixtureEl.querySelector('.dropdown') + + const keydown = createEvent('keydown') + keydown.key = 'ArrowDown' + + const keyup = createEvent('keyup') + keyup.key = 'ArrowUp' + + const handleArrowDown = () => { + expect(triggerDropdown).toHaveClass('show') + expect(triggerDropdown.getAttribute('aria-expanded')).toEqual('true') + setTimeout(() => { + dropdown.hide() + keydown.key = 'ArrowUp' + triggerDropdown.dispatchEvent(keyup) + }, 20) + } + + const handleArrowUp = () => { + expect(triggerDropdown).toHaveClass('show') + expect(triggerDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + } + + dropdown.addEventListener('shown.bs.dropdown', event => { + if (event.target.key === 'ArrowDown') { + handleArrowDown() + } else { + handleArrowUp() + } + }) + + triggerDropdown.dispatchEvent(keydown) + }) + }) + + it('should allow `data-bs-toggle="dropdown"` click events to bubble up', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const clickListener = jasmine.createSpy('clickListener') + const delegatedClickListener = jasmine.createSpy('delegatedClickListener') + + btnDropdown.addEventListener('click', clickListener) + document.addEventListener('click', delegatedClickListener) + + btnDropdown.click() + + expect(clickListener).toHaveBeenCalled() + expect(delegatedClickListener).toHaveBeenCalled() + }) + + it('should open the dropdown when clicking the child element inside `data-bs-toggle="dropdown"`', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') + const childElement = fixtureEl.querySelector('#childElement') + + btnDropdown.addEventListener('shown.bs.dropdown', () => setTimeout(() => { + expect(btnDropdown).toHaveClass('show') + expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') + resolve() + })) + + childElement.click() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/jquery.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/jquery.spec.js new file mode 100644 index 00000000..7d7f29dc --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/jquery.spec.js @@ -0,0 +1,60 @@ +/* eslint-env jquery */ + +import Alert from '../../src/alert.js' +import Button from '../../src/button.js' +import Carousel from '../../src/carousel.js' +import Collapse from '../../src/collapse.js' +import Dropdown from '../../src/dropdown.js' +import Modal from '../../src/modal.js' +import Offcanvas from '../../src/offcanvas.js' +import Popover from '../../src/popover.js' +import ScrollSpy from '../../src/scrollspy.js' +import Tab from '../../src/tab.js' +import Toast from '../../src/toast.js' +import Tooltip from '../../src/tooltip.js' +import { clearFixture, getFixture } from '../helpers/fixture.js' + +describe('jQuery', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + it('should add all plugins in jQuery', () => { + expect(Alert.jQueryInterface).toEqual(jQuery.fn.alert) + expect(Button.jQueryInterface).toEqual(jQuery.fn.button) + expect(Carousel.jQueryInterface).toEqual(jQuery.fn.carousel) + expect(Collapse.jQueryInterface).toEqual(jQuery.fn.collapse) + expect(Dropdown.jQueryInterface).toEqual(jQuery.fn.dropdown) + expect(Modal.jQueryInterface).toEqual(jQuery.fn.modal) + expect(Offcanvas.jQueryInterface).toEqual(jQuery.fn.offcanvas) + expect(Popover.jQueryInterface).toEqual(jQuery.fn.popover) + expect(ScrollSpy.jQueryInterface).toEqual(jQuery.fn.scrollspy) + expect(Tab.jQueryInterface).toEqual(jQuery.fn.tab) + expect(Toast.jQueryInterface).toEqual(jQuery.fn.toast) + expect(Tooltip.jQueryInterface).toEqual(jQuery.fn.tooltip) + }) + + it('should use jQuery event system', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + $(fixtureEl).find('.alert') + .one('closed.bs.alert', () => { + expect($(fixtureEl).find('.alert')).toHaveSize(0) + resolve() + }) + + $(fixtureEl).find('button').trigger('click') + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/modal.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/modal.spec.js new file mode 100644 index 00000000..2aa0b765 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/modal.spec.js @@ -0,0 +1,1329 @@ +import EventHandler from '../../src/dom/event-handler.js' +import Modal from '../../src/modal.js' +import ScrollBarHelper from '../../src/util/scrollbar.js' +import { + clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Modal', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + clearBodyAndDocument() + document.body.classList.remove('modal-open') + + for (const backdrop of document.querySelectorAll('.modal-backdrop')) { + backdrop.remove() + } + }) + + beforeEach(() => { + clearBodyAndDocument() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Modal.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Modal.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Modal.DATA_KEY).toEqual('bs.modal') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modalBySelector = new Modal('.modal') + const modalByElement = new Modal(modalEl) + + expect(modalBySelector._element).toEqual(modalEl) + expect(modalByElement._element).toEqual(modalEl) + }) + }) + + describe('toggle', () => { + it('should call ScrollBarHelper to handle scrollBar on body', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const spyHide = spyOn(ScrollBarHelper.prototype, 'hide').and.callThrough() + const spyReset = spyOn(ScrollBarHelper.prototype, 'reset').and.callThrough() + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(spyHide).toHaveBeenCalled() + modal.toggle() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spyReset).toHaveBeenCalled() + resolve() + }) + + modal.toggle() + }) + }) + }) + + describe('show', () => { + it('should show a modal', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modalEl.addEventListener('show.bs.modal', event => { + expect(event).toBeDefined() + }) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modalEl.getAttribute('aria-modal')).toEqual('true') + expect(modalEl.getAttribute('role')).toEqual('dialog') + expect(modalEl.getAttribute('aria-hidden')).toBeNull() + expect(modalEl.style.display).toEqual('block') + expect(document.querySelector('.modal-backdrop')).not.toBeNull() + resolve() + }) + + modal.show() + }) + }) + + it('should show a modal without backdrop', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: false + }) + + modalEl.addEventListener('show.bs.modal', event => { + expect(event).toBeDefined() + }) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modalEl.getAttribute('aria-modal')).toEqual('true') + expect(modalEl.getAttribute('role')).toEqual('dialog') + expect(modalEl.getAttribute('aria-hidden')).toBeNull() + expect(modalEl.style.display).toEqual('block') + expect(document.querySelector('.modal-backdrop')).toBeNull() + resolve() + }) + + modal.show() + }) + }) + + it('should show a modal and append the element', () => { + return new Promise(resolve => { + const modalEl = document.createElement('div') + const id = 'dynamicModal' + + modalEl.setAttribute('id', id) + modalEl.classList.add('modal') + modalEl.innerHTML = '' + + const modal = new Modal(modalEl) + + modalEl.addEventListener('shown.bs.modal', () => { + const dynamicModal = document.getElementById(id) + expect(dynamicModal).not.toBeNull() + dynamicModal.remove() + resolve() + }) + + modal.show() + }) + }) + + it('should do nothing if a modal is shown', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(EventHandler, 'trigger') + modal._isShown = true + + modal.show() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should do nothing if a modal is transitioning', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(EventHandler, 'trigger') + modal._isTransitioning = true + + modal.show() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should not fire shown event when show is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modalEl.addEventListener('show.bs.modal', event => { + event.preventDefault() + + const expectedDone = () => { + expect().nothing() + resolve() + } + + setTimeout(expectedDone, 10) + }) + + modalEl.addEventListener('shown.bs.modal', () => { + reject(new Error('shown event triggered')) + }) + + modal.show() + }) + }) + + it('should be shown after the first call to show() has been prevented while fading is enabled ', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + let prevented = false + modalEl.addEventListener('show.bs.modal', event => { + if (!prevented) { + event.preventDefault() + prevented = true + + setTimeout(() => { + modal.show() + }) + } + }) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(prevented).toBeTrue() + expect(modal._isAnimated()).toBeTrue() + resolve() + }) + + modal.show() + }) + }) + it('should set is transitioning if fade class is present', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modalEl.addEventListener('show.bs.modal', () => { + setTimeout(() => { + expect(modal._isTransitioning).toBeTrue() + }) + }) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modal._isTransitioning).toBeFalse() + resolve() + }) + + modal.show() + }) + }) + + it('should close modal when a click occurred on data-bs-dismiss="modal" inside modal', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const btnClose = fixtureEl.querySelector('[data-bs-dismiss="modal"]') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, 'hide').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + btnClose.click() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should close modal when a click occurred on a data-bs-dismiss="modal" with "bs-target" outside of modal element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const btnClose = fixtureEl.querySelector('[data-bs-dismiss="modal"]') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, 'hide').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + btnClose.click() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should set .modal\'s scroll top to 0', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modalEl.scrollTop).toEqual(0) + resolve() + }) + + modal.show() + }) + }) + + it('should set modal body scroll top to 0 if modal body do not exists', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const modalBody = modalEl.querySelector('.modal-body') + const modal = new Modal(modalEl) + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modalBody.scrollTop).toEqual(0) + resolve() + }) + + modal.show() + }) + }) + + it('should not trap focus if focus equal to false', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + focus: false + }) + + const spy = spyOn(modal._focustrap, 'activate').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should add listener when escape touch is pressed', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, 'hide').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + const keydownEscape = createEvent('keydown') + keydownEscape.key = 'Escape' + + modalEl.dispatchEvent(keydownEscape) + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should do nothing when the pressed key is not escape', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, 'hide') + + const expectDone = () => { + expect(spy).not.toHaveBeenCalled() + + resolve() + } + + modalEl.addEventListener('shown.bs.modal', () => { + const keydownTab = createEvent('keydown') + keydownTab.key = 'Tab' + + modalEl.dispatchEvent(keydownTab) + setTimeout(expectDone, 30) + }) + + modal.show() + }) + }) + + it('should adjust dialog on resize', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, '_adjustDialog').and.callThrough() + + const expectDone = () => { + expect(spy).toHaveBeenCalled() + + resolve() + } + + modalEl.addEventListener('shown.bs.modal', () => { + const resizeEvent = createEvent('resize') + + window.dispatchEvent(resizeEvent) + setTimeout(expectDone, 10) + }) + + modal.show() + }) + }) + + it('should not close modal when clicking on modal-content', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const shownCallback = () => { + setTimeout(() => { + expect(modal._isShown).toEqual(true) + resolve() + }, 10) + } + + modalEl.addEventListener('shown.bs.modal', () => { + fixtureEl.querySelector('.modal-dialog').click() + fixtureEl.querySelector('.modal-content').click() + shownCallback() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + reject(new Error('Should not hide a modal')) + }) + + modal.show() + }) + }) + + it('should not close modal when clicking outside of modal-content if backdrop = false', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: false + }) + + const shownCallback = () => { + setTimeout(() => { + expect(modal._isShown).toBeTrue() + resolve() + }, 10) + } + + modalEl.addEventListener('shown.bs.modal', () => { + modalEl.click() + shownCallback() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + reject(new Error('Should not hide a modal')) + }) + + modal.show() + }) + }) + + it('should not close modal when clicking outside of modal-content if backdrop = static', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: 'static' + }) + + const shownCallback = () => { + setTimeout(() => { + expect(modal._isShown).toBeTrue() + resolve() + }, 10) + } + + modalEl.addEventListener('shown.bs.modal', () => { + modalEl.click() + shownCallback() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + reject(new Error('Should not hide a modal')) + }) + + modal.show() + }) + }) + it('should close modal when escape key is pressed with keyboard = true and backdrop is static', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: 'static', + keyboard: true + }) + + const shownCallback = () => { + setTimeout(() => { + expect(modal._isShown).toBeFalse() + resolve() + }, 10) + } + + modalEl.addEventListener('shown.bs.modal', () => { + const keydownEscape = createEvent('keydown') + keydownEscape.key = 'Escape' + + modalEl.dispatchEvent(keydownEscape) + shownCallback() + }) + + modal.show() + }) + }) + + it('should not close modal when escape key is pressed with keyboard = false', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + keyboard: false + }) + + const shownCallback = () => { + setTimeout(() => { + expect(modal._isShown).toBeTrue() + resolve() + }, 10) + } + + modalEl.addEventListener('shown.bs.modal', () => { + const keydownEscape = createEvent('keydown') + keydownEscape.key = 'Escape' + + modalEl.dispatchEvent(keydownEscape) + shownCallback() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + reject(new Error('Should not hide a modal')) + }) + + modal.show() + }) + }) + + it('should not overflow when clicking outside of modal-content if backdrop = static', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: 'static' + }) + + modalEl.addEventListener('shown.bs.modal', () => { + modalEl.click() + setTimeout(() => { + expect(modalEl.clientHeight).toEqual(modalEl.scrollHeight) + resolve() + }, 20) + }) + + modal.show() + }) + }) + + it('should not queue multiple callbacks when clicking outside of modal-content and backdrop = static', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: 'static' + }) + + modalEl.addEventListener('shown.bs.modal', () => { + const spy = spyOn(modal, '_queueCallback').and.callThrough() + const mouseDown = createEvent('mousedown') + + modalEl.dispatchEvent(mouseDown) + modalEl.click() + modalEl.dispatchEvent(mouseDown) + modalEl.click() + + setTimeout(() => { + expect(spy).toHaveBeenCalledTimes(1) + resolve() + }, 20) + }) + + modal.show() + }) + }) + + it('should trap focus', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(modal._focustrap, 'activate').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + }) + + describe('hide', () => { + it('should hide a modal', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + const backdropSpy = spyOn(modal._backdrop, 'hide').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + modal.hide() + }) + + modalEl.addEventListener('hide.bs.modal', event => { + expect(event).toBeDefined() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(modalEl.getAttribute('aria-modal')).toBeNull() + expect(modalEl.getAttribute('role')).toBeNull() + expect(modalEl.getAttribute('aria-hidden')).toEqual('true') + expect(modalEl.style.display).toEqual('none') + expect(backdropSpy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should close modal when clicking outside of modal-content', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const dialogEl = modalEl.querySelector('.modal-dialog') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, 'hide') + + modalEl.addEventListener('shown.bs.modal', () => { + const mouseDown = createEvent('mousedown') + + dialogEl.dispatchEvent(mouseDown) + modalEl.click() + expect(spy).not.toHaveBeenCalled() + + modalEl.dispatchEvent(mouseDown) + modalEl.click() + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should not close modal when clicking on an element removed from modal content', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const buttonEl = modalEl.querySelector('.btn') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, 'hide') + buttonEl.addEventListener('click', () => { + buttonEl.remove() + }) + + modalEl.addEventListener('shown.bs.modal', () => { + modalEl.dispatchEvent(createEvent('mousedown')) + buttonEl.click() + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should do nothing is the modal is not shown', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modal.hide() + + expect().nothing() + }) + + it('should do nothing is the modal is transitioning', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modal._isTransitioning = true + modal.hide() + + expect().nothing() + }) + + it('should not hide a modal if hide is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + modalEl.addEventListener('shown.bs.modal', () => { + modal.hide() + }) + + const hideCallback = () => { + setTimeout(() => { + expect(modal._isShown).toBeTrue() + resolve() + }, 10) + } + + modalEl.addEventListener('hide.bs.modal', event => { + event.preventDefault() + hideCallback() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + reject(new Error('should not trigger hidden')) + }) + + modal.show() + }) + }) + + it('should release focus trap', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + const spy = spyOn(modal._focustrap, 'deactivate').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + modal.hide() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + }) + + describe('dispose', () => { + it('should dispose a modal', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + const focustrap = modal._focustrap + const spyDeactivate = spyOn(focustrap, 'deactivate').and.callThrough() + + expect(Modal.getInstance(modalEl)).toEqual(modal) + + const spyOff = spyOn(EventHandler, 'off') + + modal.dispose() + + expect(Modal.getInstance(modalEl)).toBeNull() + expect(spyOff).toHaveBeenCalledTimes(3) + expect(spyDeactivate).toHaveBeenCalled() + }) + }) + + describe('handleUpdate', () => { + it('should call adjust dialog', () => { + fixtureEl.innerHTML = '' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + + const spy = spyOn(modal, '_adjustDialog') + + modal.handleUpdate() + + expect(spy).toHaveBeenCalled() + }) + }) + + describe('data-api', () => { + it('should toggle modal', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modalEl.getAttribute('aria-modal')).toEqual('true') + expect(modalEl.getAttribute('role')).toEqual('dialog') + expect(modalEl.getAttribute('aria-hidden')).toBeNull() + expect(modalEl.style.display).toEqual('block') + expect(document.querySelector('.modal-backdrop')).not.toBeNull() + setTimeout(() => trigger.click(), 10) + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(modalEl.getAttribute('aria-modal')).toBeNull() + expect(modalEl.getAttribute('role')).toBeNull() + expect(modalEl.getAttribute('aria-hidden')).toEqual('true') + expect(modalEl.style.display).toEqual('none') + expect(document.querySelector('.modal-backdrop')).toBeNull() + resolve() + }) + + trigger.click() + }) + }) + + it('should not recreate a new modal', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl) + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + const spy = spyOn(modal, 'show').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + trigger.click() + }) + }) + + it('should prevent default when the trigger is or ', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + expect(modalEl.getAttribute('aria-modal')).toEqual('true') + expect(modalEl.getAttribute('role')).toEqual('dialog') + expect(modalEl.getAttribute('aria-hidden')).toBeNull() + expect(modalEl.style.display).toEqual('block') + expect(document.querySelector('.modal-backdrop')).not.toBeNull() + expect(spy).toHaveBeenCalled() + resolve() + }) + + trigger.click() + }) + }) + + it('should focus the trigger on hide', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + const spy = spyOn(trigger, 'focus') + + modalEl.addEventListener('shown.bs.modal', () => { + const modal = Modal.getInstance(modalEl) + + modal.hide() + }) + + const hideListener = () => { + setTimeout(() => { + expect(spy).toHaveBeenCalled() + resolve() + }, 20) + } + + modalEl.addEventListener('hidden.bs.modal', () => { + hideListener() + }) + + trigger.click() + }) + }) + + it('should open modal, having special characters in its id', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + modalEl.addEventListener('shown.bs.modal', () => { + resolve() + }) + + trigger.click() + }) + }) + + it('should not prevent default when a click occurred on data-bs-dismiss="modal" where tagName is DIFFERENT than or ', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const btnClose = fixtureEl.querySelector('button[data-bs-dismiss="modal"]') + const modal = new Modal(modalEl) + + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + btnClose.click() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + + it('should prevent default when a click occurred on data-bs-dismiss="modal" where tagName is or ', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const btnClose = fixtureEl.querySelector('a[data-bs-dismiss="modal"]') + const modal = new Modal(modalEl) + + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + modalEl.addEventListener('shown.bs.modal', () => { + btnClose.click() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + modal.show() + }) + }) + it('should not focus the trigger if the modal is not visible', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + const spy = spyOn(trigger, 'focus') + + modalEl.addEventListener('shown.bs.modal', () => { + const modal = Modal.getInstance(modalEl) + + modal.hide() + }) + + const hideListener = () => { + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + resolve() + }, 20) + } + + modalEl.addEventListener('hidden.bs.modal', () => { + hideListener() + }) + + trigger.click() + }) + }) + it('should not focus the trigger if the modal is not shown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const modalEl = fixtureEl.querySelector('.modal') + const trigger = fixtureEl.querySelector('[data-bs-toggle="modal"]') + + const spy = spyOn(trigger, 'focus') + + const showListener = () => { + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + resolve() + }, 10) + } + + modalEl.addEventListener('show.bs.modal', event => { + event.preventDefault() + showListener() + }) + + trigger.click() + }) + }) + + it('should call hide first, if another modal is open', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '', + '' + ].join('') + + const trigger2 = fixtureEl.querySelector('button') + const modalEl1 = document.querySelector('#modal1') + const modalEl2 = document.querySelector('#modal2') + const modal1 = new Modal(modalEl1) + + modalEl1.addEventListener('shown.bs.modal', () => { + trigger2.click() + }) + modalEl1.addEventListener('hidden.bs.modal', () => { + expect(Modal.getInstance(modalEl2)).not.toBeNull() + expect(modalEl2).toHaveClass('show') + resolve() + }) + modal1.show() + }) + }) + }) + describe('jQueryInterface', () => { + it('should create a modal', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.modal = Modal.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.modal.call(jQueryMock) + + expect(Modal.getInstance(div)).not.toBeNull() + }) + + it('should create a modal with given config', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.modal = Modal.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.modal.call(jQueryMock, { keyboard: false }) + const spy = spyOn(Modal.prototype, 'constructor') + expect(spy).not.toHaveBeenCalledWith(div, { keyboard: false }) + + const modal = Modal.getInstance(div) + expect(modal).not.toBeNull() + expect(modal._config.keyboard).toBeFalse() + }) + + it('should not re create a modal', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + const modal = new Modal(div) + + jQueryMock.fn.modal = Modal.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.modal.call(jQueryMock) + + expect(Modal.getInstance(div)).toEqual(modal) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.modal = Modal.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.modal.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should call show method', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + const modal = new Modal(div) + + jQueryMock.fn.modal = Modal.jQueryInterface + jQueryMock.elements = [div] + + const spy = spyOn(modal, 'show') + + jQueryMock.fn.modal.call(jQueryMock, 'show') + + expect(spy).toHaveBeenCalled() + }) + + it('should not call show method', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.modal = Modal.jQueryInterface + jQueryMock.elements = [div] + + const spy = spyOn(Modal.prototype, 'show') + + jQueryMock.fn.modal.call(jQueryMock) + + expect(spy).not.toHaveBeenCalled() + }) + }) + + describe('getInstance', () => { + it('should return modal instance', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + const modal = new Modal(div) + + expect(Modal.getInstance(div)).toEqual(modal) + expect(Modal.getInstance(div)).toBeInstanceOf(Modal) + }) + + it('should return null when there is no modal instance', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + + expect(Modal.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return modal instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const modal = new Modal(div) + + expect(Modal.getOrCreateInstance(div)).toEqual(modal) + expect(Modal.getInstance(div)).toEqual(Modal.getOrCreateInstance(div, {})) + expect(Modal.getOrCreateInstance(div)).toBeInstanceOf(Modal) + }) + + it('should return new instance when there is no modal instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Modal.getInstance(div)).toBeNull() + expect(Modal.getOrCreateInstance(div)).toBeInstanceOf(Modal) + }) + + it('should return new instance when there is no modal instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Modal.getInstance(div)).toBeNull() + const modal = Modal.getOrCreateInstance(div, { + backdrop: true + }) + expect(modal).toBeInstanceOf(Modal) + + expect(modal._config.backdrop).toBeTrue() + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const modal = new Modal(div, { + backdrop: true + }) + expect(Modal.getInstance(div)).toEqual(modal) + + const modal2 = Modal.getOrCreateInstance(div, { + backdrop: false + }) + expect(modal).toBeInstanceOf(Modal) + expect(modal2).toEqual(modal) + + expect(modal2._config.backdrop).toBeTrue() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/offcanvas.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/offcanvas.spec.js new file mode 100644 index 00000000..3b6c98c1 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/offcanvas.spec.js @@ -0,0 +1,914 @@ +import EventHandler from '../../src/dom/event-handler.js' +import Offcanvas from '../../src/offcanvas.js' +import { isVisible } from '../../src/util/index.js' +import ScrollBarHelper from '../../src/util/scrollbar.js' +import { + clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Offcanvas', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + document.body.classList.remove('offcanvas-open') + clearBodyAndDocument() + }) + + beforeEach(() => { + clearBodyAndDocument() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Offcanvas.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Offcanvas.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Offcanvas.DATA_KEY).toEqual('bs.offcanvas') + }) + }) + + describe('constructor', () => { + it('should call hide when a element with data-bs-dismiss="offcanvas" is clicked', () => { + fixtureEl.innerHTML = [ + '
    ', + ' Close', + '
    ' + ].join('') + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const closeEl = fixtureEl.querySelector('a') + const offCanvas = new Offcanvas(offCanvasEl) + + const spy = spyOn(offCanvas, 'hide') + + closeEl.click() + + expect(offCanvas._config.keyboard).toBeTrue() + expect(spy).toHaveBeenCalled() + }) + + it('should hide if esc is pressed', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + const keyDownEsc = createEvent('keydown') + keyDownEsc.key = 'Escape' + + const spy = spyOn(offCanvas, 'hide') + + offCanvasEl.dispatchEvent(keyDownEsc) + + expect(spy).toHaveBeenCalled() + }) + + it('should hide if esc is pressed and backdrop is static', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { backdrop: 'static' }) + const keyDownEsc = createEvent('keydown') + keyDownEsc.key = 'Escape' + + const spy = spyOn(offCanvas, 'hide') + + offCanvasEl.dispatchEvent(keyDownEsc) + + expect(spy).toHaveBeenCalled() + }) + + it('should not hide if esc is not pressed', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + const keydownTab = createEvent('keydown') + keydownTab.key = 'Tab' + + const spy = spyOn(offCanvas, 'hide') + + offCanvasEl.dispatchEvent(keydownTab) + + expect(spy).not.toHaveBeenCalled() + }) + + it('should not hide if esc is pressed but with keyboard = false', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { keyboard: false }) + const keyDownEsc = createEvent('keydown') + keyDownEsc.key = 'Escape' + + const spy = spyOn(offCanvas, 'hide') + const hidePreventedSpy = jasmine.createSpy('hidePrevented') + offCanvasEl.addEventListener('hidePrevented.bs.offcanvas', hidePreventedSpy) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(offCanvas._config.keyboard).toBeFalse() + offCanvasEl.dispatchEvent(keyDownEsc) + + expect(hidePreventedSpy).toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + + it('should not hide if user clicks on static backdrop', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl, { backdrop: 'static' }) + + const clickEvent = new Event('mousedown', { bubbles: true, cancelable: true }) + const spyClick = spyOn(offCanvas._backdrop._config, 'clickCallback').and.callThrough() + const spyHide = spyOn(offCanvas._backdrop, 'hide').and.callThrough() + const hidePreventedSpy = jasmine.createSpy('hidePrevented') + offCanvasEl.addEventListener('hidePrevented.bs.offcanvas', hidePreventedSpy) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(spyClick).toEqual(jasmine.any(Function)) + + offCanvas._backdrop._getElement().dispatchEvent(clickEvent) + expect(hidePreventedSpy).toHaveBeenCalled() + expect(spyHide).not.toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + + it('should call `hide` on resize, if element\'s position is not fixed any more', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + + const spy = spyOn(offCanvas, 'hide').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + const resizeEvent = createEvent('resize') + offCanvasEl.style.removeProperty('position') + + window.dispatchEvent(resizeEvent) + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + }) + + describe('config', () => { + it('should have default values', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + expect(offCanvas._config.backdrop).toBeTrue() + expect(offCanvas._backdrop._config.isVisible).toBeTrue() + expect(offCanvas._config.keyboard).toBeTrue() + expect(offCanvas._config.scroll).toBeFalse() + }) + + it('should read data attributes and override default config', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + expect(offCanvas._config.backdrop).toBeFalse() + expect(offCanvas._backdrop._config.isVisible).toBeFalse() + expect(offCanvas._config.keyboard).toBeFalse() + expect(offCanvas._config.scroll).toBeTrue() + }) + + it('given a config object must override data attributes', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { + backdrop: true, + keyboard: true, + scroll: false + }) + expect(offCanvas._config.backdrop).toBeTrue() + expect(offCanvas._config.keyboard).toBeTrue() + expect(offCanvas._config.scroll).toBeFalse() + }) + }) + + describe('options', () => { + it('if scroll is enabled, should allow body to scroll while offcanvas is open', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const spyHide = spyOn(ScrollBarHelper.prototype, 'hide').and.callThrough() + const spyReset = spyOn(ScrollBarHelper.prototype, 'reset').and.callThrough() + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { scroll: true }) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(spyHide).not.toHaveBeenCalled() + offCanvas.hide() + }) + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + expect(spyReset).not.toHaveBeenCalled() + resolve() + }) + offCanvas.show() + }) + }) + + it('if scroll is disabled, should call ScrollBarHelper to handle scrollBar on body', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const spyHide = spyOn(ScrollBarHelper.prototype, 'hide').and.callThrough() + const spyReset = spyOn(ScrollBarHelper.prototype, 'reset').and.callThrough() + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { scroll: false }) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(spyHide).toHaveBeenCalled() + offCanvas.hide() + }) + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + expect(spyReset).toHaveBeenCalled() + resolve() + }) + offCanvas.show() + }) + }) + + it('should hide a shown element if user click on backdrop', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl, { backdrop: true }) + + const clickEvent = new Event('mousedown', { bubbles: true, cancelable: true }) + const spy = spyOn(offCanvas._backdrop._config, 'clickCallback').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(offCanvas._backdrop._config.clickCallback).toEqual(jasmine.any(Function)) + + offCanvas._backdrop._getElement().dispatchEvent(clickEvent) + }) + + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + + it('should not trap focus if scroll is allowed', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { + scroll: true, + backdrop: false + }) + + const spy = spyOn(offCanvas._focustrap, 'activate').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + + it('should trap focus if scroll is allowed OR backdrop is enabled', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl, { + scroll: true, + backdrop: true + }) + + const spy = spyOn(offCanvas._focustrap, 'activate').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + }) + + describe('toggle', () => { + it('should call show method if show class is not present', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + const spy = spyOn(offCanvas, 'show') + + offCanvas.toggle() + + expect(spy).toHaveBeenCalled() + }) + + it('should call hide method if show class is present', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(offCanvasEl).toHaveClass('show') + const spy = spyOn(offCanvas, 'hide') + + offCanvas.toggle() + + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + }) + + describe('show', () => { + it('should add `showing` class during opening and `show` class on end', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + offCanvasEl.addEventListener('show.bs.offcanvas', () => { + expect(offCanvasEl).not.toHaveClass('show') + }) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(offCanvasEl).not.toHaveClass('showing') + expect(offCanvasEl).toHaveClass('show') + resolve() + }) + + offCanvas.show() + expect(offCanvasEl).toHaveClass('showing') + }) + }) + + it('should do nothing if already shown', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + offCanvas.show() + + expect(offCanvasEl).toHaveClass('show') + + const spyShow = spyOn(offCanvas._backdrop, 'show').and.callThrough() + const spyTrigger = spyOn(EventHandler, 'trigger').and.callThrough() + offCanvas.show() + + expect(spyTrigger).not.toHaveBeenCalled() + expect(spyShow).not.toHaveBeenCalled() + }) + + it('should show a hidden element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const spy = spyOn(offCanvas._backdrop, 'show').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(offCanvasEl).toHaveClass('show') + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + + it('should not fire shown when show is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const spy = spyOn(offCanvas._backdrop, 'show').and.callThrough() + + const expectEnd = () => { + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + resolve() + }, 10) + } + + offCanvasEl.addEventListener('show.bs.offcanvas', event => { + event.preventDefault() + expectEnd() + }) + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + reject(new Error('should not fire shown event')) + }) + + offCanvas.show() + }) + }) + + it('on window load, should make visible an offcanvas element, if its markup contains class "show"', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const spy = spyOn(Offcanvas.prototype, 'show').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + resolve() + }) + + window.dispatchEvent(createEvent('load')) + + const instance = Offcanvas.getInstance(offCanvasEl) + expect(instance).not.toBeNull() + expect(spy).toHaveBeenCalled() + }) + }) + + it('should trap focus', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + const spy = spyOn(offCanvas._focustrap, 'activate').and.callThrough() + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.show() + }) + }) + }) + + describe('hide', () => { + it('should add `hiding` class during closing and remover `show` & `hiding` classes on end', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + const offCanvasEl = fixtureEl.querySelector('.offcanvas') + const offCanvas = new Offcanvas(offCanvasEl) + + offCanvasEl.addEventListener('hide.bs.offcanvas', () => { + expect(offCanvasEl).not.toHaveClass('showing') + expect(offCanvasEl).toHaveClass('show') + }) + + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + expect(offCanvasEl).not.toHaveClass('hiding') + expect(offCanvasEl).not.toHaveClass('show') + resolve() + }) + + offCanvas.show() + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + offCanvas.hide() + expect(offCanvasEl).not.toHaveClass('showing') + expect(offCanvasEl).toHaveClass('hiding') + }) + }) + }) + + it('should do nothing if already shown', () => { + fixtureEl.innerHTML = '
    ' + + const spyTrigger = spyOn(EventHandler, 'trigger').and.callThrough() + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const spyHide = spyOn(offCanvas._backdrop, 'hide').and.callThrough() + + offCanvas.hide() + expect(spyHide).not.toHaveBeenCalled() + expect(spyTrigger).not.toHaveBeenCalled() + }) + + it('should hide a shown element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const spy = spyOn(offCanvas._backdrop, 'hide').and.callThrough() + offCanvas.show() + + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + expect(offCanvasEl).not.toHaveClass('show') + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.hide() + }) + }) + + it('should not fire hidden when hide is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const spy = spyOn(offCanvas._backdrop, 'hide').and.callThrough() + + offCanvas.show() + + const expectEnd = () => { + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + resolve() + }, 10) + } + + offCanvasEl.addEventListener('hide.bs.offcanvas', event => { + event.preventDefault() + expectEnd() + }) + + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + reject(new Error('should not fire hidden event')) + }) + + offCanvas.hide() + }) + }) + + it('should release focus trap', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const spy = spyOn(offCanvas._focustrap, 'deactivate').and.callThrough() + offCanvas.show() + + offCanvasEl.addEventListener('hidden.bs.offcanvas', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + offCanvas.hide() + }) + }) + }) + + describe('dispose', () => { + it('should dispose an offcanvas', () => { + fixtureEl.innerHTML = '
    ' + + const offCanvasEl = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(offCanvasEl) + const backdrop = offCanvas._backdrop + const spyDispose = spyOn(backdrop, 'dispose').and.callThrough() + const focustrap = offCanvas._focustrap + const spyDeactivate = spyOn(focustrap, 'deactivate').and.callThrough() + + expect(Offcanvas.getInstance(offCanvasEl)).toEqual(offCanvas) + + offCanvas.dispose() + + expect(spyDispose).toHaveBeenCalled() + expect(offCanvas._backdrop).toBeNull() + expect(spyDeactivate).toHaveBeenCalled() + expect(offCanvas._focustrap).toBeNull() + expect(Offcanvas.getInstance(offCanvasEl)).toBeNull() + }) + }) + + describe('data-api', () => { + it('should not prevent event for input', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const target = fixtureEl.querySelector('input') + const offCanvasEl = fixtureEl.querySelector('#offcanvasdiv1') + + offCanvasEl.addEventListener('shown.bs.offcanvas', () => { + expect(offCanvasEl).toHaveClass('show') + expect(target.checked).toBeTrue() + resolve() + }) + + target.click() + }) + }) + + it('should not call toggle on disabled elements', () => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const target = fixtureEl.querySelector('a') + + const spy = spyOn(Offcanvas.prototype, 'toggle') + + target.click() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should call hide first, if another offcanvas is open', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const trigger2 = fixtureEl.querySelector('#btn2') + const offcanvasEl1 = document.querySelector('#offcanvas1') + const offcanvasEl2 = document.querySelector('#offcanvas2') + const offcanvas1 = new Offcanvas(offcanvasEl1) + + offcanvasEl1.addEventListener('shown.bs.offcanvas', () => { + trigger2.click() + }) + offcanvasEl1.addEventListener('hidden.bs.offcanvas', () => { + expect(Offcanvas.getInstance(offcanvasEl2)).not.toBeNull() + resolve() + }) + offcanvas1.show() + }) + }) + + it('should focus on trigger element after closing offcanvas', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('#btn') + const offcanvasEl = fixtureEl.querySelector('#offcanvas') + const offcanvas = new Offcanvas(offcanvasEl) + const spy = spyOn(trigger, 'focus') + + offcanvasEl.addEventListener('shown.bs.offcanvas', () => { + offcanvas.hide() + }) + offcanvasEl.addEventListener('hidden.bs.offcanvas', () => { + setTimeout(() => { + expect(spy).toHaveBeenCalled() + resolve() + }, 5) + }) + + trigger.click() + }) + }) + + it('should not focus on trigger element after closing offcanvas, if it is not visible', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ' + ].join('') + + const trigger = fixtureEl.querySelector('#btn') + const offcanvasEl = fixtureEl.querySelector('#offcanvas') + const offcanvas = new Offcanvas(offcanvasEl) + const spy = spyOn(trigger, 'focus') + + offcanvasEl.addEventListener('shown.bs.offcanvas', () => { + trigger.style.display = 'none' + offcanvas.hide() + }) + offcanvasEl.addEventListener('hidden.bs.offcanvas', () => { + setTimeout(() => { + expect(isVisible(trigger)).toBeFalse() + expect(spy).not.toHaveBeenCalled() + resolve() + }, 5) + }) + + trigger.click() + }) + }) + }) + + describe('jQueryInterface', () => { + it('should create an offcanvas', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.offcanvas.call(jQueryMock) + + expect(Offcanvas.getInstance(div)).not.toBeNull() + }) + + it('should not re create an offcanvas', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(div) + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.offcanvas.call(jQueryMock) + + expect(Offcanvas.getInstance(div)).toEqual(offCanvas) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.offcanvas.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should throw error on protected method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = '_getConfig' + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.offcanvas.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should throw error if method "constructor" is being called', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'constructor' + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.offcanvas.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should call offcanvas method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + const spy = spyOn(Offcanvas.prototype, 'show') + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.offcanvas.call(jQueryMock, 'show') + expect(spy).toHaveBeenCalled() + }) + + it('should create a offcanvas with given config', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.offcanvas.call(jQueryMock, { scroll: true }) + + const offcanvas = Offcanvas.getInstance(div) + expect(offcanvas).not.toBeNull() + expect(offcanvas._config.scroll).toBeTrue() + }) + }) + + describe('getInstance', () => { + it('should return offcanvas instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const offCanvas = new Offcanvas(div) + + expect(Offcanvas.getInstance(div)).toEqual(offCanvas) + expect(Offcanvas.getInstance(div)).toBeInstanceOf(Offcanvas) + }) + + it('should return null when there is no offcanvas instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Offcanvas.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return offcanvas instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const offcanvas = new Offcanvas(div) + + expect(Offcanvas.getOrCreateInstance(div)).toEqual(offcanvas) + expect(Offcanvas.getInstance(div)).toEqual(Offcanvas.getOrCreateInstance(div, {})) + expect(Offcanvas.getOrCreateInstance(div)).toBeInstanceOf(Offcanvas) + }) + + it('should return new instance when there is no Offcanvas instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Offcanvas.getInstance(div)).toBeNull() + expect(Offcanvas.getOrCreateInstance(div)).toBeInstanceOf(Offcanvas) + }) + + it('should return new instance when there is no offcanvas instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Offcanvas.getInstance(div)).toBeNull() + const offcanvas = Offcanvas.getOrCreateInstance(div, { + scroll: true + }) + expect(offcanvas).toBeInstanceOf(Offcanvas) + + expect(offcanvas._config.scroll).toBeTrue() + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const offcanvas = new Offcanvas(div, { + scroll: true + }) + expect(Offcanvas.getInstance(div)).toEqual(offcanvas) + + const offcanvas2 = Offcanvas.getOrCreateInstance(div, { + scroll: false + }) + expect(offcanvas).toBeInstanceOf(Offcanvas) + expect(offcanvas2).toEqual(offcanvas) + + expect(offcanvas2._config.scroll).toBeTrue() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/popover.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/popover.spec.js new file mode 100644 index 00000000..da5821e7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/popover.spec.js @@ -0,0 +1,487 @@ +import EventHandler from '../../src/dom/event-handler.js' +import Popover from '../../src/popover.js' +import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js' + +describe('Popover', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + + const popoverList = document.querySelectorAll('.popover') + + for (const popoverEl of popoverList) { + popoverEl.remove() + } + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Popover.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Popover.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('NAME', () => { + it('should return plugin name', () => { + expect(Popover.NAME).toEqual(jasmine.any(String)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Popover.DATA_KEY).toEqual('bs.popover') + }) + }) + + describe('EVENT_KEY', () => { + it('should return plugin event key', () => { + expect(Popover.EVENT_KEY).toEqual('.bs.popover') + }) + }) + + describe('DefaultType', () => { + it('should return plugin default type', () => { + expect(Popover.DefaultType).toEqual(jasmine.any(Object)) + }) + }) + + describe('show', () => { + it('should toggle a popover after show', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + popoverEl.addEventListener('shown.bs.popover', () => { + expect(document.querySelector('.popover')).not.toBeNull() + popover.toggle() + }) + popoverEl.addEventListener('hidden.bs.popover', () => { + expect(document.querySelector('.popover')).toBeNull() + resolve() + }) + + popover.show() + }) + }) + + it('should show a popover', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + popoverEl.addEventListener('shown.bs.popover', () => { + expect(document.querySelector('.popover')).not.toBeNull() + resolve() + }) + + popover.show() + }) + }) + + it('should set title and content from functions', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + title: () => 'Bootstrap', + content: () => 'loves writing tests (╯°□°)╯︵ ┻━┻' + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('Bootstrap') + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('loves writing tests (╯°□°)╯︵ ┻━┻') + resolve() + }) + + popover.show() + }) + }) + + it('should call content and title functions with trigger element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + title(el) { + return el.dataset.foo + }, + content(el) { + return el.dataset.foo + } + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('bar') + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('bar') + resolve() + }) + + popover.show() + }) + }) + + it('should call content and title functions with correct this value', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + title() { + return this.dataset.foo + }, + content() { + return this.dataset.foo + } + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('bar') + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('bar') + resolve() + }) + + popover.show() + }) + }) + + it('should show a popover with just content without having header', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'Nice link' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + content: 'Some beautiful content :)' + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-header')).toBeNull() + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('Some beautiful content :)') + resolve() + }) + + popover.show() + }) + }) + + it('should show a popover with just title without having body', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'Nice link' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + title: 'Title which does not require content' + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-body')).toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('Title which does not require content') + resolve() + }) + + popover.show() + }) + }) + + it('should show a popover with just title without having body using data-attribute to get config', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'Nice link' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-body')).toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('Title which does not require content') + resolve() + }) + + popover.show() + }) + }) + + it('should NOT show a popover without `title` and `content`', () => { + fixtureEl.innerHTML = 'Nice link' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { animation: false }) + const spy = spyOn(EventHandler, 'trigger').and.callThrough() + + popover.show() + + expect(spy).not.toHaveBeenCalledWith(popoverEl, Popover.eventName('show')) + expect(document.querySelector('.popover')).toBeNull() + }) + + it('"setContent" should keep the initial template', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + popover.setContent({ '.tooltip-inner': 'foo' }) + const tip = popover._getTipElement() + + expect(tip).toHaveClass('popover') + expect(tip).toHaveClass('bs-popover-auto') + expect(tip.querySelector('.popover-arrow')).not.toBeNull() + expect(tip.querySelector('.popover-header')).not.toBeNull() + expect(tip.querySelector('.popover-body')).not.toBeNull() + }) + + it('should call setContent once', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + content: 'Popover content' + }) + expect(popover._templateFactory).toBeNull() + let spy = null + let times = 1 + + popoverEl.addEventListener('hidden.bs.popover', () => { + popover.show() + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + spy = spy || spyOn(popover._templateFactory, 'constructor').and.callThrough() + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('Popover content') + expect(spy).toHaveBeenCalledTimes(0) + if (times > 1) { + resolve() + } + + times++ + popover.hide() + }) + popover.show() + }) + }) + + it('should show a popover with provided custom class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + popoverEl.addEventListener('shown.bs.popover', () => { + const tip = document.querySelector('.popover') + expect(tip).not.toBeNull() + expect(tip).toHaveClass('custom-class') + resolve() + }) + + popover.show() + }) + }) + }) + + describe('hide', () => { + it('should hide a popover', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + popoverEl.addEventListener('shown.bs.popover', () => { + popover.hide() + }) + + popoverEl.addEventListener('hidden.bs.popover', () => { + expect(document.querySelector('.popover')).toBeNull() + resolve() + }) + + popover.show() + }) + }) + }) + + describe('jQueryInterface', () => { + it('should create a popover', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + + jQueryMock.fn.popover = Popover.jQueryInterface + jQueryMock.elements = [popoverEl] + + jQueryMock.fn.popover.call(jQueryMock) + + expect(Popover.getInstance(popoverEl)).not.toBeNull() + }) + + it('should create a popover with a config object', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + + jQueryMock.fn.popover = Popover.jQueryInterface + jQueryMock.elements = [popoverEl] + + jQueryMock.fn.popover.call(jQueryMock, { + content: 'Popover content' + }) + + expect(Popover.getInstance(popoverEl)).not.toBeNull() + }) + + it('should not re create a popover', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + jQueryMock.fn.popover = Popover.jQueryInterface + jQueryMock.elements = [popoverEl] + + jQueryMock.fn.popover.call(jQueryMock) + + expect(Popover.getInstance(popoverEl)).toEqual(popover) + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const action = 'undefinedMethod' + + jQueryMock.fn.popover = Popover.jQueryInterface + jQueryMock.elements = [popoverEl] + + expect(() => { + jQueryMock.fn.popover.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should should call show method', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + jQueryMock.fn.popover = Popover.jQueryInterface + jQueryMock.elements = [popoverEl] + + const spy = spyOn(popover, 'show') + + jQueryMock.fn.popover.call(jQueryMock, 'show') + + expect(spy).toHaveBeenCalled() + }) + }) + + describe('getInstance', () => { + it('should return popover instance', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl) + + expect(Popover.getInstance(popoverEl)).toEqual(popover) + expect(Popover.getInstance(popoverEl)).toBeInstanceOf(Popover) + }) + + it('should return null when there is no popover instance', () => { + fixtureEl.innerHTML = 'BS X' + + const popoverEl = fixtureEl.querySelector('a') + + expect(Popover.getInstance(popoverEl)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return popover instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const popover = new Popover(div) + + expect(Popover.getOrCreateInstance(div)).toEqual(popover) + expect(Popover.getInstance(div)).toEqual(Popover.getOrCreateInstance(div, {})) + expect(Popover.getOrCreateInstance(div)).toBeInstanceOf(Popover) + }) + + it('should return new instance when there is no popover instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Popover.getInstance(div)).toBeNull() + expect(Popover.getOrCreateInstance(div)).toBeInstanceOf(Popover) + }) + + it('should return new instance when there is no popover instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Popover.getInstance(div)).toBeNull() + const popover = Popover.getOrCreateInstance(div, { + placement: 'top' + }) + expect(popover).toBeInstanceOf(Popover) + + expect(popover._config.placement).toEqual('top') + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const popover = new Popover(div, { + placement: 'top' + }) + expect(Popover.getInstance(div)).toEqual(popover) + + const popover2 = Popover.getOrCreateInstance(div, { + placement: 'bottom' + }) + expect(popover).toBeInstanceOf(Popover) + expect(popover2).toEqual(popover) + + expect(popover2._config.placement).toEqual('top') + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/scrollspy.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/scrollspy.spec.js new file mode 100644 index 00000000..fc44471c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/scrollspy.spec.js @@ -0,0 +1,980 @@ +import EventHandler from '../../src/dom/event-handler.js' +import ScrollSpy from '../../src/scrollspy.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('ScrollSpy', () => { + let fixtureEl + + const getElementScrollSpy = element => element.scrollTo ? + spyOn(element, 'scrollTo').and.callThrough() : + spyOnProperty(element, 'scrollTop', 'set').and.callThrough() + + const scrollTo = (el, height) => { + el.scrollTop = height + } + + const onScrollStop = (callback, element, timeout = 30) => { + let handle = null + const onScroll = function () { + if (handle) { + window.clearTimeout(handle) + } + + handle = setTimeout(() => { + element.removeEventListener('scroll', onScroll) + callback() + }, timeout + 1) + } + + element.addEventListener('scroll', onScroll) + } + + const getDummyFixture = () => { + return [ + '', + '
    ', + '
    div 1
    ', + '
    ' + ].join('') + } + + const testElementIsActiveAfterScroll = ({ elementSelector, targetSelector, contentEl, scrollSpy, cb }) => { + const element = fixtureEl.querySelector(elementSelector) + const target = fixtureEl.querySelector(targetSelector) + // add top padding to fix Chrome on Android failures + const paddingTop = 0 + const parentOffset = getComputedStyle(contentEl).getPropertyValue('position') === 'relative' ? 0 : contentEl.offsetTop + const scrollHeight = (target.offsetTop - parentOffset) + paddingTop + + contentEl.addEventListener('activate.bs.scrollspy', event => { + if (scrollSpy._activeTarget !== element) { + return + } + + expect(element).toHaveClass('active') + expect(scrollSpy._activeTarget).toEqual(element) + expect(event.relatedTarget).toEqual(element) + cb() + }) + + setTimeout(() => { // in case we scroll something before the test + scrollTo(contentEl, scrollHeight) + }, 100) + } + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(ScrollSpy.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(ScrollSpy.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(ScrollSpy.DATA_KEY).toEqual('bs.scrollspy') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = getDummyFixture() + + const sSpyEl = fixtureEl.querySelector('.content') + const sSpyBySelector = new ScrollSpy('.content') + const sSpyByElement = new ScrollSpy(sSpyEl) + + expect(sSpyBySelector._element).toEqual(sSpyEl) + expect(sSpyByElement._element).toEqual(sSpyEl) + }) + + it('should null, if element is not scrollable', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    test
    ', + '
    ' + ].join('') + + const scrollSpy = new ScrollSpy(fixtureEl.querySelector('#content'), { + target: '#navigation' + }) + + expect(scrollSpy._observer.root).toBeNull() + expect(scrollSpy._rootElement).toBeNull() + }) + + it('should respect threshold option', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + ' ', + '
    ' + ].join('') + + const scrollSpy = new ScrollSpy('#content', { + target: '#navigation', + threshold: [1] + }) + + expect(scrollSpy._observer.thresholds).toEqual([1]) + }) + + it('should respect threshold option markup', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + ' ', + '
    ' + ].join('') + + const scrollSpy = new ScrollSpy('#content', { + target: '#navigation' + }) + + // See https://stackoverflow.com/a/45592926 + const expectToBeCloseToArray = (actual, expected) => { + expect(actual.length).toBe(expected.length) + for (const x of actual) { + const i = actual.indexOf(x) + expect(x).withContext(`[${i}]`).toBeCloseTo(expected[i]) + } + } + + expectToBeCloseToArray(scrollSpy._observer.thresholds, [0, 0.2, 1]) + }) + + it('should not take count to not visible sections', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    test
    ', + ' ', + ' ', + '
    ' + ].join('') + + const scrollSpy = new ScrollSpy(fixtureEl.querySelector('#content'), { + target: '#navigation' + }) + + expect(scrollSpy._observableSections.size).toBe(1) + expect(scrollSpy._targetLinks.size).toBe(1) + }) + + it('should not process element without target', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    test
    ', + '
    test2
    ', + '
    ' + ].join('') + + const scrollSpy = new ScrollSpy(fixtureEl.querySelector('#content'), { + target: '#navigation' + }) + + expect(scrollSpy._targetLinks).toHaveSize(2) + }) + + it('should only switch "active" class on current target', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    Overview
    ', + '
    Detail
    ', + '
    ', + '
    ' + ].join('') + + const scrollSpyEl = fixtureEl.querySelector('#scrollspy-example') + const rootEl = fixtureEl.querySelector('#root') + const scrollSpy = new ScrollSpy(scrollSpyEl, { + target: 'ss-target' + }) + + const spy = spyOn(scrollSpy, '_process').and.callThrough() + + onScrollStop(() => { + expect(rootEl).toHaveClass('active') + expect(spy).toHaveBeenCalled() + resolve() + }, scrollSpyEl) + + scrollTo(scrollSpyEl, 350) + }) + }) + + it('should not process data if `activeTarget` is same as given target', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    div 2
    ', + '
    ' + ].join('') + + const contentEl = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(contentEl, { + offset: 0, + target: '.navbar' + }) + + const triggerSpy = spyOn(EventHandler, 'trigger').and.callThrough() + + scrollSpy._activeTarget = fixtureEl.querySelector('#a-1') + testElementIsActiveAfterScroll({ + elementSelector: '#a-1', + targetSelector: '#div-1', + contentEl, + scrollSpy, + cb: reject + }) + + setTimeout(() => { + expect(triggerSpy).not.toHaveBeenCalled() + resolve() + }, 100) + }) + }) + + it('should only switch "active" class on current target specified w element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    Overview
    ', + '
    Detail
    ', + '
    ', + '
    ' + ].join('') + + const scrollSpyEl = fixtureEl.querySelector('#scrollspy-example') + const rootEl = fixtureEl.querySelector('#root') + const scrollSpy = new ScrollSpy(scrollSpyEl, { + target: fixtureEl.querySelector('#ss-target') + }) + + const spy = spyOn(scrollSpy, '_process').and.callThrough() + + onScrollStop(() => { + expect(rootEl).toHaveClass('active') + expect(scrollSpy._activeTarget).toEqual(fixtureEl.querySelector('[href="#detail"]')) + expect(spy).toHaveBeenCalled() + resolve() + }, scrollSpyEl) + + scrollTo(scrollSpyEl, 350) + }) + }) + + it('should add the active class to the correct element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    div 2
    ', + '
    ' + ].join('') + + const contentEl = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(contentEl, { + offset: 0, + target: '.navbar' + }) + + testElementIsActiveAfterScroll({ + elementSelector: '#a-1', + targetSelector: '#div-1', + contentEl, + scrollSpy, + cb() { + testElementIsActiveAfterScroll({ + elementSelector: '#a-2', + targetSelector: '#div-2', + contentEl, + scrollSpy, + cb: resolve + }) + } + }) + }) + }) + + it('should add to nav the active class to the correct element (nav markup)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    div 2
    ', + '
    ' + ].join('') + + const contentEl = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(contentEl, { + offset: 0, + target: '.navbar' + }) + + testElementIsActiveAfterScroll({ + elementSelector: '#a-1', + targetSelector: '#div-1', + contentEl, + scrollSpy, + cb() { + testElementIsActiveAfterScroll({ + elementSelector: '#a-2', + targetSelector: '#div-2', + contentEl, + scrollSpy, + cb: resolve + }) + } + }) + }) + }) + + it('should add to list-group, the active class to the correct element (list-group markup)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    div 2
    ', + '
    ' + ].join('') + + const contentEl = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(contentEl, { + offset: 0, + target: '.navbar' + }) + + testElementIsActiveAfterScroll({ + elementSelector: '#a-1', + targetSelector: '#div-1', + contentEl, + scrollSpy, + cb() { + testElementIsActiveAfterScroll({ + elementSelector: '#a-2', + targetSelector: '#div-2', + contentEl, + scrollSpy, + cb: resolve + }) + } + }) + }) + }) + + it('should clear selection if above the first section', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '', + '
    ', + '
    ', + '
    text
    ', + '
    text
    ', + '
    text
    ', + '
    ', + '
    ' + ].join('') + + const contentEl = fixtureEl.querySelector('#content') + const scrollSpy = new ScrollSpy(contentEl, { + target: '#navigation', + offset: contentEl.offsetTop + }) + const spy = spyOn(scrollSpy, '_process').and.callThrough() + + onScrollStop(() => { + const active = () => fixtureEl.querySelector('.active') + expect(spy).toHaveBeenCalled() + + expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1) + expect(active().getAttribute('id')).toEqual('two-link') + onScrollStop(() => { + expect(active()).toBeNull() + resolve() + }, contentEl) + scrollTo(contentEl, 0) + }, contentEl) + + scrollTo(contentEl, 200) + }) + }) + + it('should not clear selection if above the first section and first section is at the top', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '', + '
    ', + '
    test
    ', + '
    test
    ', + '
    test
    ', + '
    test
    ', + '
    ' + ].join('') + + const negativeHeight = 0 + const startOfSectionTwo = 101 + const contentEl = fixtureEl.querySelector('#content') + // eslint-disable-next-line no-unused-vars + const scrollSpy = new ScrollSpy(contentEl, { + target: '#navigation', + rootMargin: '0px 0px -50%' + }) + + onScrollStop(() => { + const activeId = () => fixtureEl.querySelector('.active').getAttribute('id') + + expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1) + expect(activeId()).toEqual('two-link') + scrollTo(contentEl, negativeHeight) + + onScrollStop(() => { + expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1) + expect(activeId()).toEqual('one-link') + resolve() + }, contentEl) + + scrollTo(contentEl, 0) + }, contentEl) + + scrollTo(contentEl, startOfSectionTwo) + }) + }) + + it('should correctly select navigation element on backward scrolling when each target section height is 100%', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    div 2
    ', + '
    div 3
    ', + '
    div 4
    ', + '
    div 5
    ', + '
    ' + ].join('') + + const contentEl = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(contentEl, { + offset: 0, + target: '.navbar' + }) + + scrollTo(contentEl, 0) + testElementIsActiveAfterScroll({ + elementSelector: '#li-100-5', + targetSelector: '#div-100-5', + contentEl, + scrollSpy, + cb() { + scrollTo(contentEl, 0) + testElementIsActiveAfterScroll({ + elementSelector: '#li-100-2', + targetSelector: '#div-100-2', + contentEl, + scrollSpy, + cb() { + scrollTo(contentEl, 0) + testElementIsActiveAfterScroll({ + elementSelector: '#li-100-3', + targetSelector: '#div-100-3', + contentEl, + scrollSpy, + cb() { + scrollTo(contentEl, 0) + testElementIsActiveAfterScroll({ + elementSelector: '#li-100-2', + targetSelector: '#div-100-2', + contentEl, + scrollSpy, + cb() { + scrollTo(contentEl, 0) + testElementIsActiveAfterScroll({ + elementSelector: '#li-100-1', + targetSelector: '#div-100-1', + contentEl, + scrollSpy, + cb: resolve + }) + } + }) + } + }) + } + }) + } + }) + }) + }) + }) + + describe('refresh', () => { + it('should disconnect existing observer', () => { + fixtureEl.innerHTML = getDummyFixture() + + const el = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(el) + + const spy = spyOn(scrollSpy._observer, 'disconnect') + + scrollSpy.refresh() + + expect(spy).toHaveBeenCalled() + }) + }) + + describe('dispose', () => { + it('should dispose a scrollspy', () => { + fixtureEl.innerHTML = getDummyFixture() + + const el = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(el) + + expect(ScrollSpy.getInstance(el)).not.toBeNull() + + scrollSpy.dispose() + + expect(ScrollSpy.getInstance(el)).toBeNull() + }) + }) + + describe('jQueryInterface', () => { + it('should create a scrollspy', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.scrollspy.call(jQueryMock, { target: '#navBar' }) + + expect(ScrollSpy.getInstance(div)).not.toBeNull() + }) + + it('should create a scrollspy with given config', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.scrollspy.call(jQueryMock, { rootMargin: '100px' }) + const spy = spyOn(ScrollSpy.prototype, 'constructor') + expect(spy).not.toHaveBeenCalledWith(div, { rootMargin: '100px' }) + + const scrollspy = ScrollSpy.getInstance(div) + expect(scrollspy).not.toBeNull() + expect(scrollspy._config.rootMargin).toEqual('100px') + }) + + it('should not re create a scrollspy', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(div) + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.scrollspy.call(jQueryMock) + + expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy) + }) + + it('should call a scrollspy method', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(div) + + const spy = spyOn(scrollSpy, 'refresh') + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.scrollspy.call(jQueryMock, 'refresh') + + expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy) + expect(spy).toHaveBeenCalled() + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const action = 'undefinedMethod' + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.scrollspy.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should throw error on protected method', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const action = '_getConfig' + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.scrollspy.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + + it('should throw error if method "constructor" is being called', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const action = 'constructor' + + jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.scrollspy.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('getInstance', () => { + it('should return scrollspy instance', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const scrollSpy = new ScrollSpy(div, { target: fixtureEl.querySelector('#navBar') }) + + expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy) + expect(ScrollSpy.getInstance(div)).toBeInstanceOf(ScrollSpy) + }) + + it('should return null if there is no instance', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + expect(ScrollSpy.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return scrollspy instance', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const scrollspy = new ScrollSpy(div) + + expect(ScrollSpy.getOrCreateInstance(div)).toEqual(scrollspy) + expect(ScrollSpy.getInstance(div)).toEqual(ScrollSpy.getOrCreateInstance(div, {})) + expect(ScrollSpy.getOrCreateInstance(div)).toBeInstanceOf(ScrollSpy) + }) + + it('should return new instance when there is no scrollspy instance', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + + expect(ScrollSpy.getInstance(div)).toBeNull() + expect(ScrollSpy.getOrCreateInstance(div)).toBeInstanceOf(ScrollSpy) + }) + + it('should return new instance when there is no scrollspy instance with given configuration', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + + expect(ScrollSpy.getInstance(div)).toBeNull() + const scrollspy = ScrollSpy.getOrCreateInstance(div, { + offset: 1 + }) + expect(scrollspy).toBeInstanceOf(ScrollSpy) + + expect(scrollspy._config.offset).toEqual(1) + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const scrollspy = new ScrollSpy(div, { + offset: 1 + }) + expect(ScrollSpy.getInstance(div)).toEqual(scrollspy) + + const scrollspy2 = ScrollSpy.getOrCreateInstance(div, { + offset: 2 + }) + expect(scrollspy).toBeInstanceOf(ScrollSpy) + expect(scrollspy2).toEqual(scrollspy) + + expect(scrollspy2._config.offset).toEqual(1) + }) + }) + + describe('event handler', () => { + it('should create scrollspy on window load event', () => { + fixtureEl.innerHTML = [ + '' + + '
    ' + ].join('') + + const scrollSpyEl = fixtureEl.querySelector('#wrapper') + + window.dispatchEvent(createEvent('load')) + + expect(ScrollSpy.getInstance(scrollSpyEl)).not.toBeNull() + }) + }) + + describe('SmoothScroll', () => { + it('should not enable smoothScroll', () => { + fixtureEl.innerHTML = getDummyFixture() + const offSpy = spyOn(EventHandler, 'off').and.callThrough() + const onSpy = spyOn(EventHandler, 'on').and.callThrough() + + const div = fixtureEl.querySelector('.content') + const target = fixtureEl.querySelector('#navBar') + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1 + }) + + expect(offSpy).not.toHaveBeenCalledWith(target, 'click.bs.scrollspy') + expect(onSpy).not.toHaveBeenCalledWith(target, 'click.bs.scrollspy') + }) + + it('should enable smoothScroll', () => { + fixtureEl.innerHTML = getDummyFixture() + const offSpy = spyOn(EventHandler, 'off').and.callThrough() + const onSpy = spyOn(EventHandler, 'on').and.callThrough() + + const div = fixtureEl.querySelector('.content') + const target = fixtureEl.querySelector('#navBar') + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1, + smoothScroll: true + }) + + expect(offSpy).toHaveBeenCalledWith(target, 'click.bs.scrollspy') + expect(onSpy).toHaveBeenCalledWith(target, 'click.bs.scrollspy', '[href]', jasmine.any(Function)) + }) + + it('should not smoothScroll to element if it not handles a scrollspy section', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('.content') + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1, + smoothScroll: true + }) + + const clickSpy = getElementScrollSpy(div) + + fixtureEl.querySelector('#anchor-2').click() + expect(clickSpy).not.toHaveBeenCalled() + }) + + it('should call `scrollTop` if element doesn\'t not support `scrollTo`', () => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const link = fixtureEl.querySelector('[href="#div-jsm-1"]') + delete div.scrollTo + const clickSpy = getElementScrollSpy(div) + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1, + smoothScroll: true + }) + + link.click() + expect(clickSpy).toHaveBeenCalled() + }) + + it('should smoothScroll to the proper observable element on anchor click', done => { + fixtureEl.innerHTML = getDummyFixture() + + const div = fixtureEl.querySelector('.content') + const link = fixtureEl.querySelector('[href="#div-jsm-1"]') + const observable = fixtureEl.querySelector('#div-jsm-1') + const clickSpy = getElementScrollSpy(div) + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1, + smoothScroll: true + }) + + setTimeout(() => { + if (div.scrollTo) { + expect(clickSpy).toHaveBeenCalledWith({ top: observable.offsetTop - div.offsetTop, behavior: 'smooth' }) + } else { + expect(clickSpy).toHaveBeenCalledWith(observable.offsetTop - div.offsetTop) + } + + done() + }, 100) + link.click() + }) + + it('should smoothscroll to observable with anchor link that contains a french word as id', done => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    div 1
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('.content') + const link = fixtureEl.querySelector('[href="#présentation"]') + const observable = fixtureEl.querySelector('#présentation') + const clickSpy = getElementScrollSpy(div) + // eslint-disable-next-line no-new + new ScrollSpy(div, { + offset: 1, + smoothScroll: true + }) + + setTimeout(() => { + if (div.scrollTo) { + expect(clickSpy).toHaveBeenCalledWith({ top: observable.offsetTop - div.offsetTop, behavior: 'smooth' }) + } else { + expect(clickSpy).toHaveBeenCalledWith(observable.offsetTop - div.offsetTop) + } + + done() + }, 100) + link.click() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tab.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tab.spec.js new file mode 100644 index 00000000..4fcf8ee0 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tab.spec.js @@ -0,0 +1,1252 @@ +import Tab from '../../src/tab.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Tab', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Tab.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = [ + '', + '
      ', + '
    • ', + '
    ' + ].join('') + + const tabEl = fixtureEl.querySelector('[href="#home"]') + const tabBySelector = new Tab('[href="#home"]') + const tabByElement = new Tab(tabEl) + + expect(tabBySelector._element).toEqual(tabEl) + expect(tabByElement._element).toEqual(tabEl) + }) + + it('Do not Throw exception if not parent', () => { + fixtureEl.innerHTML = [ + fixtureEl.innerHTML = '
    ' + ].join('') + const navEl = fixtureEl.querySelector('.nav-link') + + expect(() => { + new Tab(navEl) // eslint-disable-line no-new + }).not.toThrowError(TypeError) + }) + }) + + describe('show', () => { + it('should activate element by tab id (using buttons, the preferred semantic way)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
      ', + '
    • ', + '
    • ', + '
    ' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true') + resolve() + }) + + tab.show() + }) + }) + + it('should activate element by tab id (using links for tabs - not ideal, but still supported)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
      ', + '
    • ', + '
    • ', + '
    ' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true') + resolve() + }) + + tab.show() + }) + }) + + it('should activate element by tab id in ordered list', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
      ', + '
    1. ', + '
    2. ', + '
    ' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) + + tab.show() + }) + }) + + it('should activate element by tab id in nav list', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) + + tab.show() + }) + }) + + it('should activate element by tab id in list group', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) + + tab.show() + }) + }) + + it('should work with tab id being an int', done => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + ' Working Tab 1 (#tab1) Content Here', + '
    ', + '
    ', + ' Working Tab 2 (#2) with numeric ID', + '
    ', + '
    ' + ].join('') + const profileTriggerEl = fixtureEl.querySelector('#trigger2') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector(`#${CSS.escape('2')}`)).toHaveClass('active') + done() + }) + + tab.show() + }) + + it('should not fire shown when show is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const navEl = fixtureEl.querySelector('.nav > div') + const tab = new Tab(navEl) + const expectDone = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + } + + navEl.addEventListener('show.bs.tab', ev => { + ev.preventDefault() + expectDone() + }) + + navEl.addEventListener('shown.bs.tab', () => { + reject(new Error('should not trigger shown event')) + }) + + tab.show() + }) + }) + + it('should not fire shown when tab is already active', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const triggerActive = fixtureEl.querySelector('button.active') + const tab = new Tab(triggerActive) + + triggerActive.addEventListener('shown.bs.tab', () => { + reject(new Error('should not trigger shown event')) + }) + + tab.show() + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + }) + }) + + it('show and shown events should reference correct relatedTarget', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const secondTabTrigger = fixtureEl.querySelector('#triggerProfile') + const secondTab = new Tab(secondTabTrigger) + + secondTabTrigger.addEventListener('show.bs.tab', ev => { + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#home') + }) + + secondTabTrigger.addEventListener('shown.bs.tab', ev => { + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#home') + expect(secondTabTrigger.getAttribute('aria-selected')).toEqual('true') + expect(fixtureEl.querySelector('button:not(.active)').getAttribute('aria-selected')).toEqual('false') + resolve() + }) + + secondTab.show() + }) + }) + + it('should fire hide and hidden events', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerList = fixtureEl.querySelectorAll('button') + const firstTab = new Tab(triggerList[0]) + const secondTab = new Tab(triggerList[1]) + + let hideCalled = false + triggerList[0].addEventListener('shown.bs.tab', () => { + secondTab.show() + }) + + triggerList[0].addEventListener('hide.bs.tab', ev => { + hideCalled = true + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#profile') + }) + + triggerList[0].addEventListener('hidden.bs.tab', ev => { + expect(hideCalled).toBeTrue() + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#profile') + resolve() + }) + + firstTab.show() + }) + }) + + it('should not fire hidden when hide is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const triggerList = fixtureEl.querySelectorAll('button') + const firstTab = new Tab(triggerList[0]) + const secondTab = new Tab(triggerList[1]) + const expectDone = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + } + + triggerList[0].addEventListener('shown.bs.tab', () => { + secondTab.show() + }) + + triggerList[0].addEventListener('hide.bs.tab', ev => { + ev.preventDefault() + expectDone() + }) + + triggerList[0].addEventListener('hidden.bs.tab', () => { + reject(new Error('should not trigger hidden')) + }) + + firstTab.show() + }) + }) + + it('should handle removed tabs', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    test 1
    ', + '
    test 2
    ', + '
    test 3
    ', + '
    ' + ].join('') + + const secondNavEl = fixtureEl.querySelector('#secondNav') + const btnCloseEl = fixtureEl.querySelector('#btnClose') + const secondNavTab = new Tab(secondNavEl) + + secondNavEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelectorAll('.nav-tab')).toHaveSize(2) + resolve() + }) + + btnCloseEl.addEventListener('click', () => { + const linkEl = btnCloseEl.parentNode + const liEl = linkEl.parentNode + const tabId = linkEl.getAttribute('href') + const tabIdEl = fixtureEl.querySelector(tabId) + + liEl.remove() + tabIdEl.remove() + secondNavTab.show() + }) + + btnCloseEl.click() + }) + }) + + it('should not focus on opened tab', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
      ', + '
    • ', + '
    • ', + '
    ' + ].join('') + + const firstTab = fixtureEl.querySelector('#home') + firstTab.focus() + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(document.activeElement).toBe(firstTab) + expect(document.activeElement).not.toBe(profileTriggerEl) + resolve() + }) + + tab.show() + }) + }) + }) + + describe('dispose', () => { + it('should dispose a tab', () => { + fixtureEl.innerHTML = '' + + const el = fixtureEl.querySelector('.nav > div') + const tab = new Tab(fixtureEl.querySelector('.nav > div')) + + expect(Tab.getInstance(el)).not.toBeNull() + + tab.dispose() + + expect(Tab.getInstance(el)).toBeNull() + }) + }) + + describe('_activate', () => { + it('should not be called if element argument is null', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl = fixtureEl.querySelector('.nav-link') + const tab = new Tab(tabEl) + const spy = jasmine.createSpy('spy') + + const spyQueue = spyOn(tab, '_queueCallback') + tab._activate(null, spy) + expect(spyQueue).not.toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() + }) + }) + + describe('_setInitialAttributes', () => { + it('should put aria attributes', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const tabEl = fixtureEl.querySelector('.nav-link') + const parent = fixtureEl.querySelector('.nav') + const children = fixtureEl.querySelectorAll('.nav-link') + const tabPanel = fixtureEl.querySelector('#panel') + const tabPanel2 = fixtureEl.querySelector('#panel2') + + expect(parent.getAttribute('role')).toEqual(null) + expect(tabEl.getAttribute('role')).toEqual(null) + expect(tabPanel.getAttribute('role')).toEqual(null) + const tab = new Tab(tabEl) + tab._setInitialAttributes(parent, children) + + expect(parent.getAttribute('role')).toEqual('tablist') + expect(tabEl.getAttribute('role')).toEqual('tab') + + expect(tabPanel.getAttribute('role')).toEqual('tabpanel') + expect(tabPanel2.getAttribute('role')).toEqual('tabpanel') + expect(tabPanel.hasAttribute('tabindex')).toBeFalse() + expect(tabPanel.hasAttribute('tabindex2')).toBeFalse() + + expect(tabPanel.getAttribute('aria-labelledby')).toEqual('foo') + expect(tabPanel2.hasAttribute('aria-labelledby')).toBeFalse() + }) + }) + + describe('_keydown', () => { + it('if event is not one of left/right/up/down arrow, ignore it', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl = fixtureEl.querySelector('.nav-link') + const tab = new Tab(tabEl) + + const keydown = createEvent('keydown') + keydown.key = 'Enter' + const spyStop = spyOn(Event.prototype, 'stopPropagation').and.callThrough() + const spyPrevent = spyOn(Event.prototype, 'preventDefault').and.callThrough() + const spyKeydown = spyOn(tab, '_keydown') + const spyGet = spyOn(tab, '_getChildren') + + tabEl.dispatchEvent(keydown) + expect(spyKeydown).toHaveBeenCalled() + expect(spyGet).not.toHaveBeenCalled() + + expect(spyStop).not.toHaveBeenCalled() + expect(spyPrevent).not.toHaveBeenCalled() + }) + + it('if keydown event is right/down arrow, handle it', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tab1 = new Tab(tabEl1) + const tab2 = new Tab(tabEl2) + const tab3 = new Tab(tabEl3) + const spyShow1 = spyOn(tab1, 'show').and.callThrough() + const spyShow2 = spyOn(tab2, 'show').and.callThrough() + const spyShow3 = spyOn(tab3, 'show').and.callThrough() + const spyFocus1 = spyOn(tabEl1, 'focus').and.callThrough() + const spyFocus2 = spyOn(tabEl2, 'focus').and.callThrough() + const spyFocus3 = spyOn(tabEl3, 'focus').and.callThrough() + + const spyStop = spyOn(Event.prototype, 'stopPropagation').and.callThrough() + const spyPrevent = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + let keydown = createEvent('keydown') + keydown.key = 'ArrowRight' + + tabEl1.dispatchEvent(keydown) + expect(spyShow2).toHaveBeenCalled() + expect(spyFocus2).toHaveBeenCalled() + + keydown = createEvent('keydown') + keydown.key = 'ArrowDown' + + tabEl2.dispatchEvent(keydown) + expect(spyShow3).toHaveBeenCalled() + expect(spyFocus3).toHaveBeenCalled() + + tabEl3.dispatchEvent(keydown) + expect(spyShow1).toHaveBeenCalled() + expect(spyFocus1).toHaveBeenCalled() + + expect(spyStop).toHaveBeenCalledTimes(3) + expect(spyPrevent).toHaveBeenCalledTimes(3) + }) + + it('if keydown event is left arrow, handle it', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tab1 = new Tab(tabEl1) + const tab2 = new Tab(tabEl2) + const spyShow1 = spyOn(tab1, 'show').and.callThrough() + const spyShow2 = spyOn(tab2, 'show').and.callThrough() + const spyFocus1 = spyOn(tabEl1, 'focus').and.callThrough() + const spyFocus2 = spyOn(tabEl2, 'focus').and.callThrough() + + const spyStop = spyOn(Event.prototype, 'stopPropagation').and.callThrough() + const spyPrevent = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + let keydown = createEvent('keydown') + keydown.key = 'ArrowLeft' + + tabEl2.dispatchEvent(keydown) + expect(spyShow1).toHaveBeenCalled() + expect(spyFocus1).toHaveBeenCalled() + + keydown = createEvent('keydown') + keydown.key = 'ArrowUp' + + tabEl1.dispatchEvent(keydown) + expect(spyShow2).toHaveBeenCalled() + expect(spyFocus2).toHaveBeenCalled() + + expect(spyStop).toHaveBeenCalledTimes(2) + expect(spyPrevent).toHaveBeenCalledTimes(2) + }) + + it('if keydown event is Home, handle it', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl3 = fixtureEl.querySelector('#tab3') + + const tab3 = new Tab(tabEl3) + tab3.show() + + const spyShown = jasmine.createSpy() + tabEl1.addEventListener('shown.bs.tab', spyShown) + + const keydown = createEvent('keydown') + keydown.key = 'Home' + + tabEl3.dispatchEvent(keydown) + + expect(spyShown).toHaveBeenCalled() + }) + + it('if keydown event is End, handle it', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl3 = fixtureEl.querySelector('#tab3') + + const tab1 = new Tab(tabEl1) + tab1.show() + + const spyShown = jasmine.createSpy() + tabEl3.addEventListener('shown.bs.tab', spyShown) + + const keydown = createEvent('keydown') + keydown.key = 'End' + + tabEl1.dispatchEvent(keydown) + + expect(spyShown).toHaveBeenCalled() + }) + + it('if keydown event is right arrow and next element is disabled', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tabEl4 = fixtureEl.querySelector('#tab4') + const tab1 = new Tab(tabEl1) + const tab2 = new Tab(tabEl2) + const tab3 = new Tab(tabEl3) + const tab4 = new Tab(tabEl4) + const spy1 = spyOn(tab1, 'show').and.callThrough() + const spy2 = spyOn(tab2, 'show').and.callThrough() + const spy3 = spyOn(tab3, 'show').and.callThrough() + const spy4 = spyOn(tab4, 'show').and.callThrough() + const spyFocus1 = spyOn(tabEl1, 'focus').and.callThrough() + const spyFocus2 = spyOn(tabEl2, 'focus').and.callThrough() + const spyFocus3 = spyOn(tabEl3, 'focus').and.callThrough() + const spyFocus4 = spyOn(tabEl4, 'focus').and.callThrough() + + const keydown = createEvent('keydown') + keydown.key = 'ArrowRight' + + tabEl1.dispatchEvent(keydown) + expect(spy1).not.toHaveBeenCalled() + expect(spy2).not.toHaveBeenCalled() + expect(spy3).not.toHaveBeenCalled() + expect(spy4).toHaveBeenCalledTimes(1) + expect(spyFocus1).not.toHaveBeenCalled() + expect(spyFocus2).not.toHaveBeenCalled() + expect(spyFocus3).not.toHaveBeenCalled() + expect(spyFocus4).toHaveBeenCalledTimes(1) + }) + + it('if keydown event is left arrow and next element is disabled', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tabEl4 = fixtureEl.querySelector('#tab4') + const tab1 = new Tab(tabEl1) + const tab2 = new Tab(tabEl2) + const tab3 = new Tab(tabEl3) + const tab4 = new Tab(tabEl4) + const spy1 = spyOn(tab1, 'show').and.callThrough() + const spy2 = spyOn(tab2, 'show').and.callThrough() + const spy3 = spyOn(tab3, 'show').and.callThrough() + const spy4 = spyOn(tab4, 'show').and.callThrough() + const spyFocus1 = spyOn(tabEl1, 'focus').and.callThrough() + const spyFocus2 = spyOn(tabEl2, 'focus').and.callThrough() + const spyFocus3 = spyOn(tabEl3, 'focus').and.callThrough() + const spyFocus4 = spyOn(tabEl4, 'focus').and.callThrough() + + const keydown = createEvent('keydown') + keydown.key = 'ArrowLeft' + + tabEl4.dispatchEvent(keydown) + expect(spy4).not.toHaveBeenCalled() + expect(spy3).not.toHaveBeenCalled() + expect(spy2).not.toHaveBeenCalled() + expect(spy1).toHaveBeenCalledTimes(1) + expect(spyFocus4).not.toHaveBeenCalled() + expect(spyFocus3).not.toHaveBeenCalled() + expect(spyFocus2).not.toHaveBeenCalled() + expect(spyFocus1).toHaveBeenCalledTimes(1) + }) + + it('if keydown event is Home and first element is disabled', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tab3 = new Tab(tabEl3) + + tab3.show() + + const spyShown1 = jasmine.createSpy() + const spyShown2 = jasmine.createSpy() + tabEl1.addEventListener('shown.bs.tab', spyShown1) + tabEl2.addEventListener('shown.bs.tab', spyShown2) + + const keydown = createEvent('keydown') + keydown.key = 'Home' + + tabEl3.dispatchEvent(keydown) + + expect(spyShown1).not.toHaveBeenCalled() + expect(spyShown2).toHaveBeenCalled() + }) + + it('if keydown event is End and last element is disabled', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tab1 = new Tab(tabEl1) + + tab1.show() + + const spyShown2 = jasmine.createSpy() + const spyShown3 = jasmine.createSpy() + tabEl2.addEventListener('shown.bs.tab', spyShown2) + tabEl3.addEventListener('shown.bs.tab', spyShown3) + + const keydown = createEvent('keydown') + keydown.key = 'End' + + tabEl1.dispatchEvent(keydown) + + expect(spyShown3).not.toHaveBeenCalled() + expect(spyShown2).toHaveBeenCalled() + }) + }) + + describe('jQueryInterface', () => { + it('should create a tab', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('.nav > div') + + jQueryMock.fn.tab = Tab.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.tab.call(jQueryMock) + + expect(Tab.getInstance(div)).not.toBeNull() + }) + + it('should not re create a tab', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('.nav > div') + const tab = new Tab(div) + + jQueryMock.fn.tab = Tab.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.tab.call(jQueryMock) + + expect(Tab.getInstance(div)).toEqual(tab) + }) + + it('should call a tab method', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('.nav > div') + const tab = new Tab(div) + + const spy = spyOn(tab, 'show') + + jQueryMock.fn.tab = Tab.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.tab.call(jQueryMock, 'show') + + expect(Tab.getInstance(div)).toEqual(tab) + expect(spy).toHaveBeenCalled() + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('.nav > div') + const action = 'undefinedMethod' + + jQueryMock.fn.tab = Tab.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.tab.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('getInstance', () => { + it('should return null if there is no instance', () => { + expect(Tab.getInstance(fixtureEl)).toBeNull() + }) + + it('should return this instance', () => { + fixtureEl.innerHTML = '' + + const divEl = fixtureEl.querySelector('.nav > div') + const tab = new Tab(divEl) + + expect(Tab.getInstance(divEl)).toEqual(tab) + expect(Tab.getInstance(divEl)).toBeInstanceOf(Tab) + }) + }) + + describe('getOrCreateInstance', () => { + it('should return tab instance', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + const tab = new Tab(div) + + expect(Tab.getOrCreateInstance(div)).toEqual(tab) + expect(Tab.getInstance(div)).toEqual(Tab.getOrCreateInstance(div, {})) + expect(Tab.getOrCreateInstance(div)).toBeInstanceOf(Tab) + }) + + it('should return new instance when there is no tab instance', () => { + fixtureEl.innerHTML = '' + + const div = fixtureEl.querySelector('div') + + expect(Tab.getInstance(div)).toBeNull() + expect(Tab.getOrCreateInstance(div)).toBeInstanceOf(Tab) + }) + }) + + describe('data-api', () => { + it('should create dynamically a tab', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const secondTabTrigger = fixtureEl.querySelector('#triggerProfile') + + secondTabTrigger.addEventListener('shown.bs.tab', () => { + expect(secondTabTrigger).toHaveClass('active') + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) + + secondTabTrigger.click() + }) + }) + + it('selected tab should deactivate previous selected link in dropdown', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const firstLiLinkEl = fixtureEl.querySelector('li:first-child a') + + firstLiLinkEl.click() + expect(firstLiLinkEl).toHaveClass('active') + expect(fixtureEl.querySelector('li:last-child a')).not.toHaveClass('active') + expect(fixtureEl.querySelector('li:last-child .dropdown-menu a:first-child')).not.toHaveClass('active') + }) + + it('selecting a dropdown tab does not activate another', () => { + const nav1 = [ + '' + ].join('') + const nav2 = [ + '' + ].join('') + + fixtureEl.innerHTML = nav1 + nav2 + + const firstDropItem = fixtureEl.querySelector('#nav1 .dropdown-item') + + firstDropItem.click() + expect(firstDropItem).toHaveClass('active') + expect(fixtureEl.querySelector('#nav1 .dropdown-toggle')).toHaveClass('active') + expect(fixtureEl.querySelector('#nav2 .dropdown-toggle')).not.toHaveClass('active') + expect(fixtureEl.querySelector('#nav2 .dropdown-item')).not.toHaveClass('active') + }) + + it('should support li > .dropdown-item', () => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const dropItems = fixtureEl.querySelectorAll('.dropdown-item') + + dropItems[1].click() + expect(dropItems[0]).not.toHaveClass('active') + expect(dropItems[1]).toHaveClass('active') + expect(fixtureEl.querySelector('.nav-link')).not.toHaveClass('active') + }) + + it('should handle nested tabs', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + ' ', + '
    ', + '
    Nested Tab1 Content
    ', + '
    Nested Tab2 Content
    ', + '
    ', + '
    ', + '
    Tab2 Content
    ', + '
    Tab3 Content
    ', + '
    ' + ].join('') + + const tab1El = fixtureEl.querySelector('#tab1') + const tabNested2El = fixtureEl.querySelector('#tabNested2') + const xTab1El = fixtureEl.querySelector('#x-tab1') + + tabNested2El.addEventListener('shown.bs.tab', () => { + expect(xTab1El).toHaveClass('active') + resolve() + }) + + tab1El.addEventListener('shown.bs.tab', () => { + expect(xTab1El).toHaveClass('active') + tabNested2El.click() + }) + + tab1El.click() + }) + }) + + it('should not remove fade class if no active pane is present', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const triggerTabProfileEl = fixtureEl.querySelector('#tab-profile') + const triggerTabHomeEl = fixtureEl.querySelector('#tab-home') + const tabProfileEl = fixtureEl.querySelector('#profile') + const tabHomeEl = fixtureEl.querySelector('#home') + + triggerTabHomeEl.addEventListener('shown.bs.tab', () => { + setTimeout(() => { + expect(tabProfileEl).toHaveClass('fade') + expect(tabProfileEl).not.toHaveClass('show') + + expect(tabHomeEl).toHaveClass('fade') + expect(tabHomeEl).toHaveClass('show') + + resolve() + }, 10) + }) + + triggerTabProfileEl.addEventListener('shown.bs.tab', () => { + setTimeout(() => { + expect(tabProfileEl).toHaveClass('fade') + expect(tabProfileEl).toHaveClass('show') + triggerTabHomeEl.click() + }, 10) + }) + + triggerTabProfileEl.click() + }) + }) + + it('should add `show` class to tab panes if there is no `.fade` class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    test 1
    ', + '
    test 2
    ', + '
    ' + ].join('') + + const secondNavEl = fixtureEl.querySelector('#secondNav') + + secondNavEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelectorAll('.tab-content .show')).toHaveSize(1) + resolve() + }) + + secondNavEl.click() + }) + }) + + it('should add show class to tab panes if there is a `.fade` class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    test 1
    ', + '
    test 2
    ', + '
    ' + ].join('') + + const secondNavEl = fixtureEl.querySelector('#secondNav') + + secondNavEl.addEventListener('shown.bs.tab', () => { + setTimeout(() => { + expect(fixtureEl.querySelectorAll('.show')).toHaveSize(1) + resolve() + }, 10) + }) + + secondNavEl.click() + }) + }) + + it('should prevent default when the trigger is or ', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '' + ].join('') + + const tabEl = fixtureEl.querySelector('[href="#test2"]') + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + tabEl.addEventListener('shown.bs.tab', () => { + expect(tabEl).toHaveClass('active') + expect(spy).toHaveBeenCalled() + resolve() + }) + + tabEl.click() + }) + }) + + it('should not fire shown when tab has disabled attribute', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const triggerDisabled = fixtureEl.querySelector('button[disabled]') + triggerDisabled.addEventListener('shown.bs.tab', () => { + reject(new Error('should not trigger shown event')) + }) + + triggerDisabled.click() + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + }) + }) + + it('should not fire shown when tab has disabled class', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const triggerDisabled = fixtureEl.querySelector('a.disabled') + + triggerDisabled.addEventListener('shown.bs.tab', () => { + reject(new Error('should not trigger shown event')) + }) + + triggerDisabled.click() + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + }) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/toast.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/toast.spec.js new file mode 100644 index 00000000..200fe3e4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/toast.spec.js @@ -0,0 +1,672 @@ +import Toast from '../../src/toast.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Toast', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Toast.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Toast.DATA_KEY).toEqual('bs.toast') + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '
    ' + + const toastEl = fixtureEl.querySelector('.toast') + const toastBySelector = new Toast('.toast') + const toastByElement = new Toast(toastEl) + + expect(toastBySelector._element).toEqual(toastEl) + expect(toastByElement._element).toEqual(toastEl) + }) + + it('should allow to config in js', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('div') + const toast = new Toast(toastEl, { + delay: 1 + }) + + toastEl.addEventListener('shown.bs.toast', () => { + expect(toastEl).toHaveClass('show') + resolve() + }) + + toast.show() + }) + }) + + it('should close toast when close element with data-bs-dismiss attribute is set', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('div') + const toast = new Toast(toastEl) + + toastEl.addEventListener('shown.bs.toast', () => { + expect(toastEl).toHaveClass('show') + + const button = toastEl.querySelector('.btn-close') + + button.click() + }) + + toastEl.addEventListener('hidden.bs.toast', () => { + expect(toastEl).not.toHaveClass('show') + resolve() + }) + + toast.show() + }) + }) + }) + + describe('Default', () => { + it('should expose default setting to allow to override them', () => { + const defaultDelay = 1000 + + Toast.Default.delay = defaultDelay + + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('div') + const toast = new Toast(toastEl) + + expect(toast._config.delay).toEqual(defaultDelay) + }) + }) + + describe('DefaultType', () => { + it('should expose default setting types for read', () => { + expect(Toast.DefaultType).toEqual(jasmine.any(Object)) + }) + }) + + describe('show', () => { + it('should auto hide', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + toastEl.addEventListener('hidden.bs.toast', () => { + expect(toastEl).not.toHaveClass('show') + resolve() + }) + + toast.show() + }) + }) + + it('should not add fade class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + toastEl.addEventListener('shown.bs.toast', () => { + expect(toastEl).not.toHaveClass('fade') + resolve() + }) + + toast.show() + }) + }) + + it('should not trigger shown if show is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + const assertDone = () => { + setTimeout(() => { + expect(toastEl).not.toHaveClass('show') + resolve() + }, 20) + } + + toastEl.addEventListener('show.bs.toast', event => { + event.preventDefault() + assertDone() + }) + + toastEl.addEventListener('shown.bs.toast', () => { + reject(new Error('shown event should not be triggered if show is prevented')) + }) + + toast.show() + }) + }) + + it('should clear timeout if toast is shown again before it is hidden', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + setTimeout(() => { + toast._config.autohide = false + toastEl.addEventListener('shown.bs.toast', () => { + expect(spy).toHaveBeenCalled() + expect(toast._timeout).toBeNull() + resolve() + }) + toast.show() + }, toast._config.delay / 2) + + const spy = spyOn(toast, '_clearTimeout').and.callThrough() + + toast.show() + }) + }) + + it('should clear timeout if toast is interacted with mouse', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + const spy = spyOn(toast, '_clearTimeout').and.callThrough() + + setTimeout(() => { + spy.calls.reset() + + toastEl.addEventListener('mouseover', () => { + expect(toast._clearTimeout).toHaveBeenCalledTimes(1) + expect(toast._timeout).toBeNull() + resolve() + }) + + const mouseOverEvent = createEvent('mouseover') + toastEl.dispatchEvent(mouseOverEvent) + }, toast._config.delay / 2) + + toast.show() + }) + }) + + it('should clear timeout if toast is interacted with keyboard', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + ' a simple toast', + ' ', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + const spy = spyOn(toast, '_clearTimeout').and.callThrough() + + setTimeout(() => { + spy.calls.reset() + + toastEl.addEventListener('focusin', () => { + expect(toast._clearTimeout).toHaveBeenCalledTimes(1) + expect(toast._timeout).toBeNull() + resolve() + }) + + const insideFocusable = toastEl.querySelector('button') + insideFocusable.focus() + }, toast._config.delay / 2) + + toast.show() + }) + }) + + it('should still auto hide after being interacted with mouse and keyboard', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + ' a simple toast', + ' ', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + setTimeout(() => { + toastEl.addEventListener('mouseover', () => { + const insideFocusable = toastEl.querySelector('button') + insideFocusable.focus() + }) + + toastEl.addEventListener('focusin', () => { + const mouseOutEvent = createEvent('mouseout') + toastEl.dispatchEvent(mouseOutEvent) + }) + + toastEl.addEventListener('mouseout', () => { + const outsideFocusable = document.getElementById('outside-focusable') + outsideFocusable.focus() + }) + + toastEl.addEventListener('focusout', () => { + expect(toast._timeout).not.toBeNull() + resolve() + }) + + const mouseOverEvent = createEvent('mouseover') + toastEl.dispatchEvent(mouseOverEvent) + }, toast._config.delay / 2) + + toast.show() + }) + }) + + it('should not auto hide if focus leaves but mouse pointer remains inside', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + ' a simple toast', + ' ', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + setTimeout(() => { + toastEl.addEventListener('mouseover', () => { + const insideFocusable = toastEl.querySelector('button') + insideFocusable.focus() + }) + + toastEl.addEventListener('focusin', () => { + const outsideFocusable = document.getElementById('outside-focusable') + outsideFocusable.focus() + }) + + toastEl.addEventListener('focusout', () => { + expect(toast._timeout).toBeNull() + resolve() + }) + + const mouseOverEvent = createEvent('mouseover') + toastEl.dispatchEvent(mouseOverEvent) + }, toast._config.delay / 2) + + toast.show() + }) + }) + + it('should not auto hide if mouse pointer leaves but focus remains inside', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ', + ' a simple toast', + ' ', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + setTimeout(() => { + toastEl.addEventListener('mouseover', () => { + const insideFocusable = toastEl.querySelector('button') + insideFocusable.focus() + }) + + toastEl.addEventListener('focusin', () => { + const mouseOutEvent = createEvent('mouseout') + toastEl.dispatchEvent(mouseOutEvent) + }) + + toastEl.addEventListener('mouseout', () => { + expect(toast._timeout).toBeNull() + resolve() + }) + + const mouseOverEvent = createEvent('mouseover') + toastEl.dispatchEvent(mouseOverEvent) + }, toast._config.delay / 2) + + toast.show() + }) + }) + }) + + describe('hide', () => { + it('should allow to hide toast manually', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + toastEl.addEventListener('shown.bs.toast', () => { + toast.hide() + }) + + toastEl.addEventListener('hidden.bs.toast', () => { + expect(toastEl).not.toHaveClass('show') + resolve() + }) + + toast.show() + }) + }) + + it('should do nothing when we call hide on a non shown toast', () => { + fixtureEl.innerHTML = '
    ' + + const toastEl = fixtureEl.querySelector('div') + const toast = new Toast(toastEl) + + const spy = spyOn(toastEl.classList, 'contains') + + toast.hide() + + expect(spy).toHaveBeenCalled() + }) + + it('should not trigger hidden if hide is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('.toast') + const toast = new Toast(toastEl) + + const assertDone = () => { + setTimeout(() => { + expect(toastEl).toHaveClass('show') + resolve() + }, 20) + } + + toastEl.addEventListener('shown.bs.toast', () => { + toast.hide() + }) + + toastEl.addEventListener('hide.bs.toast', event => { + event.preventDefault() + assertDone() + }) + + toastEl.addEventListener('hidden.bs.toast', () => { + reject(new Error('hidden event should not be triggered if hide is prevented')) + }) + + toast.show() + }) + }) + }) + + describe('dispose', () => { + it('should allow to destroy toast', () => { + fixtureEl.innerHTML = '
    ' + + const toastEl = fixtureEl.querySelector('div') + + const toast = new Toast(toastEl) + + expect(Toast.getInstance(toastEl)).not.toBeNull() + + toast.dispose() + + expect(Toast.getInstance(toastEl)).toBeNull() + }) + + it('should allow to destroy toast and hide it before that', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + ' a simple toast', + '
    ', + '
    ' + ].join('') + + const toastEl = fixtureEl.querySelector('div') + const toast = new Toast(toastEl) + const expected = () => { + expect(toastEl).toHaveClass('show') + expect(Toast.getInstance(toastEl)).not.toBeNull() + + toast.dispose() + + expect(Toast.getInstance(toastEl)).toBeNull() + expect(toastEl).not.toHaveClass('show') + + resolve() + } + + toastEl.addEventListener('shown.bs.toast', () => { + setTimeout(expected, 1) + }) + + toast.show() + }) + }) + }) + + describe('jQueryInterface', () => { + it('should create a toast', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.toast = Toast.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.toast.call(jQueryMock) + + expect(Toast.getInstance(div)).not.toBeNull() + }) + + it('should not re create a toast', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const toast = new Toast(div) + + jQueryMock.fn.toast = Toast.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.toast.call(jQueryMock) + + expect(Toast.getInstance(div)).toEqual(toast) + }) + + it('should call a toast method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const toast = new Toast(div) + + const spy = spyOn(toast, 'show') + + jQueryMock.fn.toast = Toast.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.toast.call(jQueryMock, 'show') + + expect(Toast.getInstance(div)).toEqual(toast) + expect(spy).toHaveBeenCalled() + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.toast = Toast.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.toast.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) + + describe('getInstance', () => { + it('should return a toast instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const toast = new Toast(div) + + expect(Toast.getInstance(div)).toEqual(toast) + expect(Toast.getInstance(div)).toBeInstanceOf(Toast) + }) + + it('should return null when there is no toast instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Toast.getInstance(div)).toBeNull() + }) + }) + + describe('getOrCreateInstance', () => { + it('should return toast instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const toast = new Toast(div) + + expect(Toast.getOrCreateInstance(div)).toEqual(toast) + expect(Toast.getInstance(div)).toEqual(Toast.getOrCreateInstance(div, {})) + expect(Toast.getOrCreateInstance(div)).toBeInstanceOf(Toast) + }) + + it('should return new instance when there is no toast instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Toast.getInstance(div)).toBeNull() + expect(Toast.getOrCreateInstance(div)).toBeInstanceOf(Toast) + }) + + it('should return new instance when there is no toast instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Toast.getInstance(div)).toBeNull() + const toast = Toast.getOrCreateInstance(div, { + delay: 1 + }) + expect(toast).toBeInstanceOf(Toast) + + expect(toast._config.delay).toEqual(1) + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const toast = new Toast(div, { + delay: 1 + }) + expect(Toast.getInstance(div)).toEqual(toast) + + const toast2 = Toast.getOrCreateInstance(div, { + delay: 2 + }) + expect(toast).toBeInstanceOf(Toast) + expect(toast2).toEqual(toast) + + expect(toast2._config.delay).toEqual(1) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tooltip.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tooltip.spec.js new file mode 100644 index 00000000..37f2c230 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/tooltip.spec.js @@ -0,0 +1,1585 @@ +import EventHandler from '../../src/dom/event-handler.js' +import Tooltip from '../../src/tooltip.js' +import { noop } from '../../src/util/index.js' +import { + clearFixture, createEvent, getFixture, jQueryMock +} from '../helpers/fixture.js' + +describe('Tooltip', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + + for (const tooltipEl of document.querySelectorAll('.tooltip')) { + tooltipEl.remove() + } + }) + + describe('VERSION', () => { + it('should return plugin version', () => { + expect(Tooltip.VERSION).toEqual(jasmine.any(String)) + }) + }) + + describe('Default', () => { + it('should return plugin default config', () => { + expect(Tooltip.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('NAME', () => { + it('should return plugin name', () => { + expect(Tooltip.NAME).toEqual(jasmine.any(String)) + }) + }) + + describe('DATA_KEY', () => { + it('should return plugin data key', () => { + expect(Tooltip.DATA_KEY).toEqual('bs.tooltip') + }) + }) + + describe('EVENT_KEY', () => { + it('should return plugin event key', () => { + expect(Tooltip.EVENT_KEY).toEqual('.bs.tooltip') + }) + }) + + describe('DefaultType', () => { + it('should return plugin default type', () => { + expect(Tooltip.DefaultType).toEqual(jasmine.any(Object)) + }) + }) + + describe('constructor', () => { + it('should take care of element either passed as a CSS selector or DOM element', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('#tooltipEl') + const tooltipBySelector = new Tooltip('#tooltipEl') + const tooltipByElement = new Tooltip(tooltipEl) + + expect(tooltipBySelector._element).toEqual(tooltipEl) + expect(tooltipByElement._element).toEqual(tooltipEl) + }) + + it('should not take care of disallowed data attributes', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._config.sanitize).toBeTrue() + }) + + it('should convert title and content to string if numbers', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + title: 1, + content: 7 + }) + + expect(tooltip._config.title).toEqual('1') + expect(tooltip._config.content).toEqual('7') + }) + + it('should enable selector delegation', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const containerEl = fixtureEl.querySelector('div') + const tooltipContainer = new Tooltip(containerEl, { + selector: 'a[rel="tooltip"]', + trigger: 'click' + }) + + containerEl.innerHTML = '' + + const tooltipInContainerEl = containerEl.querySelector('a') + + tooltipInContainerEl.addEventListener('shown.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).not.toBeNull() + tooltipContainer.dispose() + resolve() + }) + + tooltipInContainerEl.click() + }) + }) + + it('should create offset modifier when offset is passed as a function', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const getOffset = jasmine.createSpy('getOffset').and.returnValue([10, 20]) + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + offset: getOffset, + popperConfig: { + onFirstUpdate(state) { + expect(getOffset).toHaveBeenCalledWith({ + popper: state.rects.popper, + reference: state.rects.reference, + placement: state.placement + }, tooltipEl) + resolve() + } + } + }) + + const offset = tooltip._getOffset() + + expect(offset).toEqual(jasmine.any(Function)) + + tooltip.show() + }) + }) + + it('should create offset modifier when offset option is passed in data attribute', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._getOffset()).toEqual([10, 20]) + }) + + it('should allow to pass config to Popper with `popperConfig`', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + popperConfig: { + placement: 'left' + } + }) + + const popperConfig = tooltip._getPopperConfig('top') + + expect(popperConfig.placement).toEqual('left') + }) + + it('should allow to pass config to Popper with `popperConfig` as a function', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const getPopperConfig = jasmine.createSpy('getPopperConfig').and.returnValue({ placement: 'left' }) + const tooltip = new Tooltip(tooltipEl, { + popperConfig: getPopperConfig + }) + + const popperConfig = tooltip._getPopperConfig('top') + + // Ensure that the function was called with the default config. + expect(getPopperConfig).toHaveBeenCalledWith(jasmine.objectContaining({ + placement: jasmine.any(String) + })) + expect(popperConfig.placement).toEqual('left') + }) + + it('should use original title, if not "data-bs-title" is given', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._getTitle()).toEqual('Another tooltip') + }) + }) + + describe('enable', () => { + it('should enable a tooltip', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.enable() + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).not.toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + }) + + describe('disable', () => { + it('should disable tooltip', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.disable() + + tooltipEl.addEventListener('show.bs.tooltip', () => { + reject(new Error('should not show a disabled tooltip')) + }) + + tooltip.show() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + }) + + describe('toggleEnabled', () => { + it('should toggle enabled', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._isEnabled).toBeTrue() + + tooltip.toggleEnabled() + + expect(tooltip._isEnabled).toBeFalse() + }) + }) + + describe('toggle', () => { + it('should do nothing if disabled', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.disable() + + tooltipEl.addEventListener('show.bs.tooltip', () => { + reject(new Error('should not show a disabled tooltip')) + }) + + tooltip.toggle() + + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + }) + }) + + it('should show a tooltip', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).not.toBeNull() + resolve() + }) + + tooltip.toggle() + }) + }) + + it('should call toggle and show the tooltip when trigger is "click"', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + trigger: 'click' + }) + + const spy = spyOn(tooltip, 'toggle').and.callThrough() + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + tooltipEl.click() + }) + }) + + it('should hide a tooltip', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + tooltip.toggle() + }) + + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).toBeNull() + resolve() + }) + + tooltip.toggle() + }) + }) + + it('should call toggle and hide the tooltip when trigger is "click"', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + trigger: 'click' + }) + + const spy = spyOn(tooltip, 'toggle').and.callThrough() + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + tooltipEl.click() + }) + + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + tooltipEl.click() + }) + }) + }) + + describe('dispose', () => { + it('should destroy a tooltip', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const addEventSpy = spyOn(tooltipEl, 'addEventListener').and.callThrough() + const removeEventSpy = spyOn(tooltipEl, 'removeEventListener').and.callThrough() + + const tooltip = new Tooltip(tooltipEl) + + expect(Tooltip.getInstance(tooltipEl)).toEqual(tooltip) + + const expectedArgs = [ + ['mouseover', jasmine.any(Function), jasmine.any(Boolean)], + ['mouseout', jasmine.any(Function), jasmine.any(Boolean)], + ['focusin', jasmine.any(Function), jasmine.any(Boolean)], + ['focusout', jasmine.any(Function), jasmine.any(Boolean)] + ] + + expect(addEventSpy.calls.allArgs()).toEqual(expectedArgs) + + tooltip.dispose() + + expect(Tooltip.getInstance(tooltipEl)).toBeNull() + expect(removeEventSpy.calls.allArgs()).toEqual(expectedArgs) + }) + + it('should destroy a tooltip after it is shown and hidden', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + tooltip.hide() + }) + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + tooltip.dispose() + expect(tooltip.tip).toBeNull() + expect(Tooltip.getInstance(tooltipEl)).toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should destroy a tooltip and remove it from the dom', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).not.toBeNull() + + tooltip.dispose() + + expect(document.querySelector('.tooltip')).toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should destroy a tooltip and reset it\'s initial title', () => { + fixtureEl.innerHTML = [ + '', + '' + ].join('') + + const tooltipWithTitleEl = fixtureEl.querySelector('#tooltipWithTitle') + const tooltip = new Tooltip('#tooltipWithTitle') + expect(tooltipWithTitleEl.getAttribute('title')).toBeNull() + tooltip.dispose() + expect(tooltipWithTitleEl.getAttribute('title')).toBe('tooltipTitle') + + const tooltipWithoutTitleEl = fixtureEl.querySelector('#tooltipWithoutTitle') + const tooltip2 = new Tooltip('#tooltipWithTitle') + expect(tooltipWithoutTitleEl.getAttribute('title')).toBeNull() + tooltip2.dispose() + expect(tooltipWithoutTitleEl.getAttribute('title')).toBeNull() + }) + }) + + describe('show', () => { + it('should show a tooltip', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tooltipShown = document.querySelector('.tooltip') + + expect(tooltipShown).not.toBeNull() + expect(tooltipEl.getAttribute('aria-describedby')).toEqual(tooltipShown.getAttribute('id')) + expect(tooltipShown.getAttribute('id')).toContain('tooltip') + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip when hovering a child element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + ' ', + ' ', + ' ', + ' ', + '' + ].join('') + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + const spy = spyOn(tooltip, 'show') + + tooltipEl.querySelector('rect').dispatchEvent(createEvent('mouseover', { bubbles: true })) + + setTimeout(() => { + expect(spy).toHaveBeenCalled() + resolve() + }, 0) + }) + }) + + it('should show a tooltip on mobile', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + document.documentElement.ontouchstart = noop + + const spy = spyOn(EventHandler, 'on').and.callThrough() + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).not.toBeNull() + expect(spy).toHaveBeenCalledWith(jasmine.any(Object), 'mouseover', noop) + document.documentElement.ontouchstart = undefined + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip relative to placement option', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + placement: 'bottom' + }) + + tooltipEl.addEventListener('inserted.bs.tooltip', () => { + expect(tooltip._getTipElement()).toHaveClass('bs-tooltip-auto') + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(tooltip._getTipElement()).toHaveClass('bs-tooltip-auto') + expect(tooltip._getTipElement().getAttribute('data-popper-placement')).toEqual('bottom') + resolve() + }) + + tooltip.show() + }) + }) + + it('should not error when trying to show a tooltip that has been removed from the dom', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + const firstCallback = () => { + tooltipEl.removeEventListener('shown.bs.tooltip', firstCallback) + let tooltipShown = document.querySelector('.tooltip') + + tooltipShown.remove() + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + tooltipShown = document.querySelector('.tooltip') + + expect(tooltipShown).not.toBeNull() + resolve() + }) + + tooltip.show() + } + + tooltipEl.addEventListener('shown.bs.tooltip', firstCallback) + + tooltip.show() + }) + }) + + it('should show a tooltip with a dom element container', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + container: fixtureEl + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(fixtureEl.querySelector('.tooltip')).not.toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip with a jquery element container', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + container: { + 0: fixtureEl, + jquery: 'jQuery' + } + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(fixtureEl.querySelector('.tooltip')).not.toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip with a selector in container', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + container: '#fixture' + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(fixtureEl.querySelector('.tooltip')).not.toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip with placement as a function', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const spy = jasmine.createSpy('placement').and.returnValue('top') + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + placement: spy + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).not.toBeNull() + expect(spy).toHaveBeenCalled() + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip without the animation', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + animation: false + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tip = document.querySelector('.tooltip') + + expect(tip).not.toBeNull() + expect(tip).not.toHaveClass('fade') + resolve() + }) + + tooltip.show() + }) + }) + + it('should throw an error the element is not visible', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + try { + tooltip.show() + } catch (error) { + expect(error.message).toEqual('Please use show on visible elements') + } + }) + + it('should not show a tooltip if show.bs.tooltip is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + const expectedDone = () => { + setTimeout(() => { + expect(document.querySelector('.tooltip')).toBeNull() + resolve() + }, 10) + } + + tooltipEl.addEventListener('show.bs.tooltip', ev => { + ev.preventDefault() + expectedDone() + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + reject(new Error('Tooltip should not be shown')) + }) + + tooltip.show() + }) + }) + + it('should show tooltip if leave event hasn\'t occurred before delay expires', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + delay: 150 + }) + + const spy = spyOn(tooltip, 'show') + + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + }, 100) + + setTimeout(() => { + expect(spy).toHaveBeenCalled() + resolve() + }, 200) + + tooltipEl.dispatchEvent(createEvent('mouseover')) + }) + }) + + it('should not show tooltip if leave event occurs before delay expires', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + delay: 150 + }) + + const spy = spyOn(tooltip, 'show') + + setTimeout(() => { + expect(spy).not.toHaveBeenCalled() + tooltipEl.dispatchEvent(createEvent('mouseover')) + }, 100) + + setTimeout(() => { + expect(spy).toHaveBeenCalled() + expect(document.querySelectorAll('.tooltip')).toHaveSize(0) + resolve() + }, 200) + + tooltipEl.dispatchEvent(createEvent('mouseover')) + }) + }) + + it('should not hide tooltip if leave event occurs and enter event occurs within the hide delay', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._config.delay).toEqual({ show: 0, hide: 150 }) + + setTimeout(() => { + expect(tooltip._getTipElement()).toHaveClass('show') + tooltipEl.dispatchEvent(createEvent('mouseout')) + + setTimeout(() => { + expect(tooltip._getTipElement()).toHaveClass('show') + tooltipEl.dispatchEvent(createEvent('mouseover')) + }, 100) + + setTimeout(() => { + expect(tooltip._getTipElement()).toHaveClass('show') + expect(document.querySelectorAll('.tooltip')).toHaveSize(1) + resolve() + }, 200) + }, 10) + + tooltipEl.dispatchEvent(createEvent('mouseover')) + }) + }) + + it('should not hide tooltip if leave event occurs and interaction remains inside trigger', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '', + 'Trigger', + 'the tooltip', + '' + ].join('') + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + const triggerChild = tooltipEl.querySelector('b') + + const spy = spyOn(tooltip, 'hide').and.callThrough() + + tooltipEl.addEventListener('mouseover', () => { + const moveMouseToChildEvent = createEvent('mouseout') + Object.defineProperty(moveMouseToChildEvent, 'relatedTarget', { + value: triggerChild + }) + + tooltipEl.dispatchEvent(moveMouseToChildEvent) + }) + + tooltipEl.addEventListener('mouseout', () => { + expect(spy).not.toHaveBeenCalled() + resolve() + }) + + tooltipEl.dispatchEvent(createEvent('mouseover')) + }) + }) + + it('should properly maintain tooltip state if leave event occurs and enter event occurs during hide transition', () => { + return new Promise(resolve => { + // Style this tooltip to give it plenty of room for popper to do what it wants + fixtureEl.innerHTML = 'Trigger' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.15s', + transitionDelay: '0s' + }) + + setTimeout(() => { + expect(tooltip._popper).not.toBeNull() + expect(tooltip._getTipElement().getAttribute('data-popper-placement')).toEqual('top') + tooltipEl.dispatchEvent(createEvent('mouseout')) + + setTimeout(() => { + expect(tooltip._getTipElement()).not.toHaveClass('show') + tooltipEl.dispatchEvent(createEvent('mouseover')) + }, 100) + + setTimeout(() => { + expect(tooltip._popper).not.toBeNull() + expect(tooltip._getTipElement().getAttribute('data-popper-placement')).toEqual('top') + resolve() + }, 200) + }, 10) + + tooltipEl.dispatchEvent(createEvent('mouseover')) + }) + }) + + it('should only trigger inserted event if a new tooltip element was created', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.15s', + transitionDelay: '0s' + }) + + const insertedFunc = jasmine.createSpy() + tooltipEl.addEventListener('inserted.bs.tooltip', insertedFunc) + + setTimeout(() => { + expect(insertedFunc).toHaveBeenCalledTimes(1) + tooltip.hide() + + setTimeout(() => { + tooltip.show() + }, 100) + + setTimeout(() => { + expect(insertedFunc).toHaveBeenCalledTimes(2) + resolve() + }, 200) + }, 0) + + tooltip.show() + }) + }) + + it('should show a tooltip with custom class provided in data attributes', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tip = document.querySelector('.tooltip') + expect(tip).not.toBeNull() + expect(tip).toHaveClass('custom-class') + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip with custom class provided as a string in config', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + customClass: 'custom-class custom-class-2' + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tip = document.querySelector('.tooltip') + expect(tip).not.toBeNull() + expect(tip).toHaveClass('custom-class') + expect(tip).toHaveClass('custom-class-2') + resolve() + }) + + tooltip.show() + }) + }) + + it('should show a tooltip with custom class provided as a function in config', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const spy = jasmine.createSpy('customClass').and.callFake(function (el) { + return `${el.dataset.classA} ${this.dataset.classB}` + }) + const tooltip = new Tooltip(tooltipEl, { + customClass: spy + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tip = document.querySelector('.tooltip') + expect(tip).not.toBeNull() + expect(spy).toHaveBeenCalled() + expect(tip).toHaveClass('custom-class-a') + expect(tip).toHaveClass('custom-class-b') + resolve() + }) + + tooltip.show() + }) + }) + + it('should remove `title` attribute if exists', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + expect(tooltipEl.getAttribute('title')).toBeNull() + resolve() + }) + tooltip.show() + }) + }) + }) + + describe('hide', () => { + it('should hide a tooltip', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => tooltip.hide()) + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).toBeNull() + expect(tooltipEl.getAttribute('aria-describedby')).toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should hide a tooltip on mobile', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + const spy = spyOn(EventHandler, 'off') + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + document.documentElement.ontouchstart = noop + tooltip.hide() + }) + + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).toBeNull() + expect(spy).toHaveBeenCalledWith(jasmine.any(Object), 'mouseover', noop) + document.documentElement.ontouchstart = undefined + resolve() + }) + + tooltip.show() + }) + }) + + it('should hide a tooltip without animation', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + animation: false + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => tooltip.hide()) + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + expect(document.querySelector('.tooltip')).toBeNull() + expect(tooltipEl.getAttribute('aria-describedby')).toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + + it('should not hide a tooltip if hide event is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '' + + const assertDone = () => { + setTimeout(() => { + expect(document.querySelector('.tooltip')).not.toBeNull() + resolve() + }, 20) + } + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + animation: false + }) + + tooltipEl.addEventListener('shown.bs.tooltip', () => tooltip.hide()) + tooltipEl.addEventListener('hide.bs.tooltip', event => { + event.preventDefault() + assertDone() + }) + tooltipEl.addEventListener('hidden.bs.tooltip', () => { + reject(new Error('should not trigger hidden event')) + }) + + tooltip.show() + }) + }) + + it('should not throw error running hide if popper hasn\'t been shown', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const tooltip = new Tooltip(div) + + try { + tooltip.hide() + expect().nothing() + } catch { + throw new Error('should not throw error') + } + }) + }) + + describe('update', () => { + it('should call popper update', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const spy = spyOn(tooltip._popper, 'update') + + tooltip.update() + + expect(spy).toHaveBeenCalled() + resolve() + }) + + tooltip.show() + }) + }) + + it('should do nothing if the tooltip is not shown', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.update() + expect().nothing() + }) + }) + + describe('_isWithContent', () => { + it('should return true if there is content', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._isWithContent()).toBeTrue() + }) + + it('should return false if there is no content', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._isWithContent()).toBeFalse() + }) + }) + + describe('_getTipElement', () => { + it('should create the tip element and return it', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + const spy = spyOn(document, 'createElement').and.callThrough() + + expect(tooltip._getTipElement()).toBeDefined() + expect(spy).toHaveBeenCalled() + }) + + it('should return the created tip element', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + const spy = spyOn(document, 'createElement').and.callThrough() + + expect(tooltip._getTipElement()).toBeDefined() + expect(spy).toHaveBeenCalled() + + spy.calls.reset() + + expect(tooltip._getTipElement()).toBeDefined() + expect(spy).not.toHaveBeenCalled() + }) + }) + + describe('setContent', () => { + it('should set tip content', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { animation: false }) + + const tip = tooltip._getTipElement() + + tooltip.setContent(tip) + + expect(tip).not.toHaveClass('show') + expect(tip).not.toHaveClass('fade') + expect(tip.querySelector('.tooltip-inner').textContent).toEqual('Another tooltip') + }) + + it('should re-show tip if it was already shown', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + tooltip.show() + const tip = () => tooltip._getTipElement() + + expect(tip()).toHaveClass('show') + tooltip.setContent({ '.tooltip-inner': 'foo' }) + + expect(tip()).toHaveClass('show') + expect(tip().querySelector('.tooltip-inner').textContent).toEqual('foo') + }) + + it('should keep tip hidden, if it was already hidden before', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + const tip = () => tooltip._getTipElement() + + expect(tip()).not.toHaveClass('show') + tooltip.setContent({ '.tooltip-inner': 'foo' }) + + expect(tip()).not.toHaveClass('show') + tooltip.show() + expect(tip().querySelector('.tooltip-inner').textContent).toEqual('foo') + }) + + it('"setContent" should keep the initial template', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.setContent({ '.tooltip-inner': 'foo' }) + const tip = tooltip._getTipElement() + + expect(tip).toHaveClass('tooltip') + expect(tip).toHaveClass('bs-tooltip-auto') + expect(tip.querySelector('.tooltip-arrow')).not.toBeNull() + expect(tip.querySelector('.tooltip-inner')).not.toBeNull() + }) + }) + + describe('setContent', () => { + it('should do nothing if the element is null', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.setContent({ '.tooltip': null }) + expect().nothing() + }) + + it('should do nothing if the content is a child of the element', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const tooltipEl = fixtureEl.querySelector('a') + const childContent = fixtureEl.querySelector('div') + const tooltip = new Tooltip(tooltipEl, { + html: true + }) + + tooltip._getTipElement().append(childContent) + tooltip.setContent({ '.tooltip': childContent }) + + expect().nothing() + }) + + it('should add the content as a child of the element for jQuery elements', () => { + fixtureEl.innerHTML = [ + '', + '
    ', + '
    ' + ].join('') + + const tooltipEl = fixtureEl.querySelector('a') + const childContent = fixtureEl.querySelector('div') + const tooltip = new Tooltip(tooltipEl, { + html: true + }) + + tooltip.setContent({ '.tooltip': { 0: childContent, jquery: 'jQuery' } }) + tooltip.show() + + expect(childContent.parentNode).toEqual(tooltip._getTipElement()) + }) + + it('should add the child text content in the element', () => { + fixtureEl.innerHTML = [ + '', + '
    Tooltip
    ', + '
    ' + ].join('') + + const tooltipEl = fixtureEl.querySelector('a') + const childContent = fixtureEl.querySelector('div') + const tooltip = new Tooltip(tooltipEl) + + tooltip.setContent({ '.tooltip': childContent }) + + expect(childContent.textContent).toEqual(tooltip._getTipElement().textContent) + }) + + it('should add html without sanitize it', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + sanitize: false, + html: true + }) + + tooltip.setContent({ '.tooltip': '
    Tooltip
    ' }) + + expect(tooltip._getTipElement().querySelector('div').id).toEqual('childContent') + }) + + it('should add html sanitized', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + html: true + }) + + const content = [ + '
    ', + ' ', + '
    ' + ].join('') + + tooltip.setContent({ '.tooltip': content }) + expect(tooltip._getTipElement().querySelector('div').id).toEqual('childContent') + expect(tooltip._getTipElement().querySelector('button')).toBeNull() + }) + + it('should add text content', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltip.setContent({ '.tooltip': 'test' }) + + expect(tooltip._getTipElement().textContent).toEqual('test') + }) + }) + + describe('_getTitle', () => { + it('should return the title', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + expect(tooltip._getTitle()).toEqual('Another tooltip') + }) + + it('should call title function', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + title: () => 'test' + }) + + expect(tooltip._getTitle()).toEqual('test') + }) + + it('should call title function with trigger element', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + title(el) { + return el.dataset.foo + } + }) + + expect(tooltip._getTitle()).toEqual('bar') + }) + + it('should call title function with correct this value', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + title() { + return this.dataset.foo + } + }) + + expect(tooltip._getTitle()).toEqual('bar') + }) + }) + + describe('getInstance', () => { + it('should return tooltip instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const alert = new Tooltip(div) + + expect(Tooltip.getInstance(div)).toEqual(alert) + expect(Tooltip.getInstance(div)).toBeInstanceOf(Tooltip) + }) + + it('should return null when there is no tooltip instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Tooltip.getInstance(div)).toBeNull() + }) + }) + + describe('aria-label', () => { + it('should add the aria-label attribute for referencing original title', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tooltipShown = document.querySelector('.tooltip') + + expect(tooltipShown).not.toBeNull() + expect(tooltipEl.getAttribute('aria-label')).toEqual('Another tooltip') + resolve() + }) + + tooltip.show() + }) + }) + + it('should add the aria-label attribute when element text content is a whitespace string', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = ' ' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tooltipShown = document.querySelector('.tooltip') + + expect(tooltipShown).not.toBeNull() + expect(tooltipEl.getAttribute('aria-label')).toEqual('A tooltip') + resolve() + }) + + tooltip.show() + }) + }) + + it('should not add the aria-label attribute if the attribute already exists', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tooltipShown = document.querySelector('.tooltip') + + expect(tooltipShown).not.toBeNull() + expect(tooltipEl.getAttribute('aria-label')).toEqual('Different label') + resolve() + }) + + tooltip.show() + }) + }) + + it('should not add the aria-label attribute if the element has text content', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'text content' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl) + + tooltipEl.addEventListener('shown.bs.tooltip', () => { + const tooltipShown = document.querySelector('.tooltip') + + expect(tooltipShown).not.toBeNull() + expect(tooltipEl.getAttribute('aria-label')).toBeNull() + resolve() + }) + + tooltip.show() + }) + }) + }) + + describe('getOrCreateInstance', () => { + it('should return tooltip instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const tooltip = new Tooltip(div) + + expect(Tooltip.getOrCreateInstance(div)).toEqual(tooltip) + expect(Tooltip.getInstance(div)).toEqual(Tooltip.getOrCreateInstance(div, {})) + expect(Tooltip.getOrCreateInstance(div)).toBeInstanceOf(Tooltip) + }) + + it('should return new instance when there is no tooltip instance', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Tooltip.getInstance(div)).toBeNull() + expect(Tooltip.getOrCreateInstance(div)).toBeInstanceOf(Tooltip) + }) + + it('should return new instance when there is no tooltip instance with given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Tooltip.getInstance(div)).toBeNull() + const tooltip = Tooltip.getOrCreateInstance(div, { + title: () => 'test' + }) + expect(tooltip).toBeInstanceOf(Tooltip) + + expect(tooltip._getTitle()).toEqual('test') + }) + + it('should return the instance when exists without given configuration', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const tooltip = new Tooltip(div, { + title: () => 'nothing' + }) + expect(Tooltip.getInstance(div)).toEqual(tooltip) + + const tooltip2 = Tooltip.getOrCreateInstance(div, { + title: () => 'test' + }) + expect(tooltip).toBeInstanceOf(Tooltip) + expect(tooltip2).toEqual(tooltip) + + expect(tooltip2._getTitle()).toEqual('nothing') + }) + }) + + describe('jQueryInterface', () => { + it('should create a tooltip', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + jQueryMock.fn.tooltip = Tooltip.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.tooltip.call(jQueryMock) + + expect(Tooltip.getInstance(div)).not.toBeNull() + }) + + it('should not re create a tooltip', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const tooltip = new Tooltip(div) + + jQueryMock.fn.tooltip = Tooltip.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.tooltip.call(jQueryMock) + + expect(Tooltip.getInstance(div)).toEqual(tooltip) + }) + + it('should call a tooltip method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const tooltip = new Tooltip(div) + + const spy = spyOn(tooltip, 'show') + + jQueryMock.fn.tooltip = Tooltip.jQueryInterface + jQueryMock.elements = [div] + + jQueryMock.fn.tooltip.call(jQueryMock, 'show') + + expect(Tooltip.getInstance(div)).toEqual(tooltip) + expect(spy).toHaveBeenCalled() + }) + + it('should throw error on undefined method', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const action = 'undefinedMethod' + + jQueryMock.fn.tooltip = Tooltip.jQueryInterface + jQueryMock.elements = [div] + + expect(() => { + jQueryMock.fn.tooltip.call(jQueryMock, action) + }).toThrowError(TypeError, `No method named "${action}"`) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/backdrop.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/backdrop.spec.js new file mode 100644 index 00000000..0faaac6a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/backdrop.spec.js @@ -0,0 +1,321 @@ +import Backdrop from '../../../src/util/backdrop.js' +import { getTransitionDurationFromElement } from '../../../src/util/index.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +const CLASS_BACKDROP = '.modal-backdrop' +const CLASS_NAME_FADE = 'fade' +const CLASS_NAME_SHOW = 'show' + +describe('Backdrop', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + const list = document.querySelectorAll(CLASS_BACKDROP) + + for (const el of list) { + el.remove() + } + }) + + describe('show', () => { + it('should append the backdrop html once on show and include the "show" class if it is "shown"', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + isAnimated: false + }) + const getElements = () => document.querySelectorAll(CLASS_BACKDROP) + + expect(getElements()).toHaveSize(0) + + instance.show() + instance.show(() => { + expect(getElements()).toHaveSize(1) + for (const el of getElements()) { + expect(el).toHaveClass(CLASS_NAME_SHOW) + } + + resolve() + }) + }) + }) + + it('should not append the backdrop html if it is not "shown"', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: false, + isAnimated: true + }) + const getElements = () => document.querySelectorAll(CLASS_BACKDROP) + + expect(getElements()).toHaveSize(0) + instance.show(() => { + expect(getElements()).toHaveSize(0) + resolve() + }) + }) + }) + + it('should append the backdrop html once and include the "fade" class if it is "shown" and "animated"', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + isAnimated: true + }) + const getElements = () => document.querySelectorAll(CLASS_BACKDROP) + + expect(getElements()).toHaveSize(0) + + instance.show(() => { + expect(getElements()).toHaveSize(1) + for (const el of getElements()) { + expect(el).toHaveClass(CLASS_NAME_FADE) + } + + resolve() + }) + }) + }) + }) + + describe('hide', () => { + it('should remove the backdrop html', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + isAnimated: true + }) + + const getElements = () => document.body.querySelectorAll(CLASS_BACKDROP) + + expect(getElements()).toHaveSize(0) + instance.show(() => { + expect(getElements()).toHaveSize(1) + instance.hide(() => { + expect(getElements()).toHaveSize(0) + resolve() + }) + }) + }) + }) + + it('should remove the "show" class', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + isAnimated: true + }) + const elem = instance._getElement() + + instance.show() + instance.hide(() => { + expect(elem).not.toHaveClass(CLASS_NAME_SHOW) + resolve() + }) + }) + }) + + it('should not try to remove Node on remove method if it is not "shown"', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: false, + isAnimated: true + }) + const getElements = () => document.querySelectorAll(CLASS_BACKDROP) + const spy = spyOn(instance, 'dispose').and.callThrough() + + expect(getElements()).toHaveSize(0) + expect(instance._isAppended).toBeFalse() + instance.show(() => { + instance.hide(() => { + expect(getElements()).toHaveSize(0) + expect(spy).not.toHaveBeenCalled() + expect(instance._isAppended).toBeFalse() + resolve() + }) + }) + }) + }) + + it('should not error if the backdrop no longer has a parent', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const wrapper = fixtureEl.querySelector('#wrapper') + const instance = new Backdrop({ + isVisible: true, + isAnimated: true, + rootElement: wrapper + }) + + const getElements = () => document.querySelectorAll(CLASS_BACKDROP) + + instance.show(() => { + wrapper.remove() + instance.hide(() => { + expect(getElements()).toHaveSize(0) + resolve() + }) + }) + }) + }) + }) + + describe('click callback', () => { + it('should execute callback on click', () => { + return new Promise(resolve => { + const spy = jasmine.createSpy('spy') + + const instance = new Backdrop({ + isVisible: true, + isAnimated: false, + clickCallback: () => spy() + }) + const endTest = () => { + setTimeout(() => { + expect(spy).toHaveBeenCalled() + resolve() + }, 10) + } + + instance.show(() => { + const clickEvent = new Event('mousedown', { bubbles: true, cancelable: true }) + document.querySelector(CLASS_BACKDROP).dispatchEvent(clickEvent) + endTest() + }) + }) + }) + + describe('animation callbacks', () => { + it('should show and hide backdrop after counting transition duration if it is animated', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + isAnimated: true + }) + const spy2 = jasmine.createSpy('spy2') + + const execDone = () => { + setTimeout(() => { + expect(spy2).toHaveBeenCalledTimes(2) + resolve() + }, 10) + } + + instance.show(spy2) + instance.hide(() => { + spy2() + execDone() + }) + expect(spy2).not.toHaveBeenCalled() + }) + }) + + it('should show and hide backdrop without a delay if it is not animated', () => { + return new Promise(resolve => { + const spy = jasmine.createSpy('spy', getTransitionDurationFromElement) + const instance = new Backdrop({ + isVisible: true, + isAnimated: false + }) + const spy2 = jasmine.createSpy('spy2') + + instance.show(spy2) + instance.hide(spy2) + + setTimeout(() => { + expect(spy2).toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() + resolve() + }, 10) + }) + }) + + it('should not call delay callbacks if it is not "shown"', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: false, + isAnimated: true + }) + const spy = jasmine.createSpy('spy', getTransitionDurationFromElement) + + instance.show() + instance.hide(() => { + expect(spy).not.toHaveBeenCalled() + resolve() + }) + }) + }) + }) + + describe('Config', () => { + describe('rootElement initialization', () => { + it('should be appended on "document.body" by default', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true + }) + const getElement = () => document.querySelector(CLASS_BACKDROP) + instance.show(() => { + expect(getElement().parentElement).toEqual(document.body) + resolve() + }) + }) + }) + + it('should find the rootElement if passed as a string', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + rootElement: 'body' + }) + const getElement = () => document.querySelector(CLASS_BACKDROP) + instance.show(() => { + expect(getElement().parentElement).toEqual(document.body) + resolve() + }) + }) + }) + + it('should be appended on any element given by the proper config', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const wrapper = fixtureEl.querySelector('#wrapper') + const instance = new Backdrop({ + isVisible: true, + rootElement: wrapper + }) + const getElement = () => document.querySelector(CLASS_BACKDROP) + instance.show(() => { + expect(getElement().parentElement).toEqual(wrapper) + resolve() + }) + }) + }) + }) + + describe('ClassName', () => { + it('should allow configuring className', () => { + return new Promise(resolve => { + const instance = new Backdrop({ + isVisible: true, + className: 'foo' + }) + const getElement = () => document.querySelector('.foo') + instance.show(() => { + expect(getElement()).toEqual(instance._getElement()) + instance.dispose() + resolve() + }) + }) + }) + }) + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/component-functions.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/component-functions.spec.js new file mode 100644 index 00000000..ce83785e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/component-functions.spec.js @@ -0,0 +1,106 @@ +import BaseComponent from '../../../src/base-component.js' +import { enableDismissTrigger } from '../../../src/util/component-functions.js' +import { clearFixture, createEvent, getFixture } from '../../helpers/fixture.js' + +class DummyClass2 extends BaseComponent { + static get NAME() { + return 'test' + } + + hide() { + return true + } + + testMethod() { + return true + } +} + +describe('Plugin functions', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('data-bs-dismiss functionality', () => { + it('should get Plugin and execute the given method, when a click occurred on data-bs-dismiss="PluginName"', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const spyGet = spyOn(DummyClass2, 'getOrCreateInstance').and.callThrough() + const spyTest = spyOn(DummyClass2.prototype, 'testMethod') + const componentWrapper = fixtureEl.querySelector('#foo') + const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]') + const event = createEvent('click') + + enableDismissTrigger(DummyClass2, 'testMethod') + btnClose.dispatchEvent(event) + + expect(spyGet).toHaveBeenCalledWith(componentWrapper) + expect(spyTest).toHaveBeenCalled() + }) + + it('if data-bs-dismiss="PluginName" hasn\'t got "data-bs-target", "getOrCreateInstance" has to be initialized by closest "plugin.Name" class', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const spyGet = spyOn(DummyClass2, 'getOrCreateInstance').and.callThrough() + const spyHide = spyOn(DummyClass2.prototype, 'hide') + const componentWrapper = fixtureEl.querySelector('#foo') + const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]') + const event = createEvent('click') + + enableDismissTrigger(DummyClass2) + btnClose.dispatchEvent(event) + + expect(spyGet).toHaveBeenCalledWith(componentWrapper) + expect(spyHide).toHaveBeenCalled() + }) + + it('if data-bs-dismiss="PluginName" is disabled, must not trigger function', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const spy = spyOn(DummyClass2, 'getOrCreateInstance').and.callThrough() + const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]') + const event = createEvent('click') + + enableDismissTrigger(DummyClass2) + btnClose.dispatchEvent(event) + + expect(spy).not.toHaveBeenCalled() + }) + + it('should prevent default when the trigger is or ', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]') + const event = createEvent('click') + + enableDismissTrigger(DummyClass2) + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + btnClose.dispatchEvent(event) + + expect(spy).toHaveBeenCalled() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/config.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/config.spec.js new file mode 100644 index 00000000..93987a74 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/config.spec.js @@ -0,0 +1,166 @@ +import Config from '../../../src/util/config.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +class DummyConfigClass extends Config { + static get NAME() { + return 'dummy' + } +} + +describe('Config', () => { + let fixtureEl + const name = 'dummy' + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('NAME', () => { + it('should return plugin NAME', () => { + expect(DummyConfigClass.NAME).toEqual(name) + }) + }) + + describe('DefaultType', () => { + it('should return plugin default type', () => { + expect(DummyConfigClass.DefaultType).toEqual(jasmine.any(Object)) + }) + }) + + describe('Default', () => { + it('should return plugin defaults', () => { + expect(DummyConfigClass.Default).toEqual(jasmine.any(Object)) + }) + }) + + describe('mergeConfigObj', () => { + it('should parse element\'s data attributes and merge it with default config. Element\'s data attributes must excel Defaults', () => { + fixtureEl.innerHTML = '
    ' + + spyOnProperty(DummyConfigClass, 'Default', 'get').and.returnValue({ + testBool: true, + testString: 'foo', + testString1: 'foo', + testInt: 7 + }) + const instance = new DummyConfigClass() + const configResult = instance._mergeConfigObj({}, fixtureEl.querySelector('#test')) + + expect(configResult.testBool).toEqual(false) + expect(configResult.testString).toEqual('foo') + expect(configResult.testString1).toEqual('bar') + expect(configResult.testInt).toEqual(8) + }) + + it('should parse element\'s data attributes and merge it with default config, plug these given during method call. The programmatically given should excel all', () => { + fixtureEl.innerHTML = '
    ' + + spyOnProperty(DummyConfigClass, 'Default', 'get').and.returnValue({ + testBool: true, + testString: 'foo', + testString1: 'foo', + testInt: 7 + }) + const instance = new DummyConfigClass() + const configResult = instance._mergeConfigObj({ + testString1: 'test', + testInt: 3 + }, fixtureEl.querySelector('#test')) + + expect(configResult.testBool).toEqual(false) + expect(configResult.testString).toEqual('foo') + expect(configResult.testString1).toEqual('test') + expect(configResult.testInt).toEqual(3) + }) + + it('should parse element\'s data attribute `config` and any rest attributes. The programmatically given should excel all. Data attribute `config` should excel only Defaults', () => { + fixtureEl.innerHTML = '
    ' + + spyOnProperty(DummyConfigClass, 'Default', 'get').and.returnValue({ + testBool: true, + testString: 'foo', + testString1: 'foo', + testInt: 7, + testInt2: 600 + }) + const instance = new DummyConfigClass() + const configResult = instance._mergeConfigObj({ + testString1: 'test' + }, fixtureEl.querySelector('#test')) + + expect(configResult.testBool).toEqual(false) + expect(configResult.testString).toEqual('foo') + expect(configResult.testString1).toEqual('test') + expect(configResult.testInt).toEqual(8) + expect(configResult.testInt2).toEqual(100) + }) + + it('should omit element\'s data attribute `config` if is not an object', () => { + fixtureEl.innerHTML = '
    ' + + spyOnProperty(DummyConfigClass, 'Default', 'get').and.returnValue({ + testInt: 7, + testInt2: 79 + }) + const instance = new DummyConfigClass() + const configResult = instance._mergeConfigObj({}, fixtureEl.querySelector('#test')) + + expect(configResult.testInt).toEqual(8) + expect(configResult.testInt2).toEqual(79) + }) + }) + + describe('typeCheckConfig', () => { + it('should check type of the config object', () => { + spyOnProperty(DummyConfigClass, 'DefaultType', 'get').and.returnValue({ + toggle: 'boolean', + parent: '(string|element)' + }) + const config = { + toggle: true, + parent: 777 + } + + const obj = new DummyConfigClass() + expect(() => { + obj._typeCheckConfig(config) + }).toThrowError(TypeError, `${obj.constructor.NAME.toUpperCase()}: Option "parent" provided type "number" but expected type "(string|element)".`) + }) + + it('should return null stringified when null is passed', () => { + spyOnProperty(DummyConfigClass, 'DefaultType', 'get').and.returnValue({ + toggle: 'boolean', + parent: '(null|element)' + }) + + const obj = new DummyConfigClass() + const config = { + toggle: true, + parent: null + } + + obj._typeCheckConfig(config) + expect().nothing() + }) + + it('should return undefined stringified when undefined is passed', () => { + spyOnProperty(DummyConfigClass, 'DefaultType', 'get').and.returnValue({ + toggle: 'boolean', + parent: '(undefined|element)' + }) + + const obj = new DummyConfigClass() + const config = { + toggle: true, + parent: undefined + } + + obj._typeCheckConfig(config) + expect().nothing() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/focustrap.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/focustrap.spec.js new file mode 100644 index 00000000..0a20017d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/focustrap.spec.js @@ -0,0 +1,218 @@ +import EventHandler from '../../../src/dom/event-handler.js' +import SelectorEngine from '../../../src/dom/selector-engine.js' +import FocusTrap from '../../../src/util/focustrap.js' +import { clearFixture, createEvent, getFixture } from '../../helpers/fixture.js' + +describe('FocusTrap', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('activate', () => { + it('should autofocus itself by default', () => { + fixtureEl.innerHTML = '
    ' + + const trapElement = fixtureEl.querySelector('div') + + const spy = spyOn(trapElement, 'focus') + + const focustrap = new FocusTrap({ trapElement }) + focustrap.activate() + + expect(spy).toHaveBeenCalled() + }) + + it('if configured not to autofocus, should not autofocus itself', () => { + fixtureEl.innerHTML = '
    ' + + const trapElement = fixtureEl.querySelector('div') + + const spy = spyOn(trapElement, 'focus') + + const focustrap = new FocusTrap({ trapElement, autofocus: false }) + focustrap.activate() + + expect(spy).not.toHaveBeenCalled() + }) + + it('should force focus inside focus trap if it can', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + 'outside', + '
    ', + ' inside', + '
    ' + ].join('') + + const trapElement = fixtureEl.querySelector('div') + const focustrap = new FocusTrap({ trapElement }) + focustrap.activate() + + const inside = document.getElementById('inside') + + const focusInListener = () => { + expect(spy).toHaveBeenCalled() + document.removeEventListener('focusin', focusInListener) + resolve() + } + + const spy = spyOn(inside, 'focus') + spyOn(SelectorEngine, 'focusableChildren').and.callFake(() => [inside]) + + document.addEventListener('focusin', focusInListener) + + const focusInEvent = createEvent('focusin', { bubbles: true }) + Object.defineProperty(focusInEvent, 'target', { + value: document.getElementById('outside') + }) + + document.dispatchEvent(focusInEvent) + }) + }) + + it('should wrap focus around forward on tab', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + 'outside', + '
    ', + ' first', + ' inside', + ' last', + '
    ' + ].join('') + + const trapElement = fixtureEl.querySelector('div') + const focustrap = new FocusTrap({ trapElement }) + focustrap.activate() + + const first = document.getElementById('first') + const inside = document.getElementById('inside') + const last = document.getElementById('last') + const outside = document.getElementById('outside') + + spyOn(SelectorEngine, 'focusableChildren').and.callFake(() => [first, inside, last]) + const spy = spyOn(first, 'focus').and.callThrough() + + const focusInListener = () => { + expect(spy).toHaveBeenCalled() + first.removeEventListener('focusin', focusInListener) + resolve() + } + + first.addEventListener('focusin', focusInListener) + + const keydown = createEvent('keydown') + keydown.key = 'Tab' + + document.dispatchEvent(keydown) + outside.focus() + }) + }) + + it('should wrap focus around backwards on shift-tab', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + 'outside', + '
    ', + ' first', + ' inside', + ' last', + '
    ' + ].join('') + + const trapElement = fixtureEl.querySelector('div') + const focustrap = new FocusTrap({ trapElement }) + focustrap.activate() + + const first = document.getElementById('first') + const inside = document.getElementById('inside') + const last = document.getElementById('last') + const outside = document.getElementById('outside') + + spyOn(SelectorEngine, 'focusableChildren').and.callFake(() => [first, inside, last]) + const spy = spyOn(last, 'focus').and.callThrough() + + const focusInListener = () => { + expect(spy).toHaveBeenCalled() + last.removeEventListener('focusin', focusInListener) + resolve() + } + + last.addEventListener('focusin', focusInListener) + + const keydown = createEvent('keydown') + keydown.key = 'Tab' + keydown.shiftKey = true + + document.dispatchEvent(keydown) + outside.focus() + }) + }) + + it('should force focus on itself if there is no focusable content', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + 'outside', + '
    ' + ].join('') + + const trapElement = fixtureEl.querySelector('div') + const focustrap = new FocusTrap({ trapElement }) + focustrap.activate() + + const focusInListener = () => { + expect(spy).toHaveBeenCalled() + document.removeEventListener('focusin', focusInListener) + resolve() + } + + const spy = spyOn(focustrap._config.trapElement, 'focus') + + document.addEventListener('focusin', focusInListener) + + const focusInEvent = createEvent('focusin', { bubbles: true }) + Object.defineProperty(focusInEvent, 'target', { + value: document.getElementById('outside') + }) + + document.dispatchEvent(focusInEvent) + }) + }) + }) + + describe('deactivate', () => { + it('should flag itself as no longer active', () => { + const focustrap = new FocusTrap({ trapElement: fixtureEl }) + focustrap.activate() + expect(focustrap._isActive).toBeTrue() + + focustrap.deactivate() + expect(focustrap._isActive).toBeFalse() + }) + + it('should remove all event listeners', () => { + const focustrap = new FocusTrap({ trapElement: fixtureEl }) + focustrap.activate() + + const spy = spyOn(EventHandler, 'off') + focustrap.deactivate() + + expect(spy).toHaveBeenCalled() + }) + + it('doesn\'t try removing event listeners unless it needs to (in case it hasn\'t been activated)', () => { + const focustrap = new FocusTrap({ trapElement: fixtureEl }) + + const spy = spyOn(EventHandler, 'off') + focustrap.deactivate() + + expect(spy).not.toHaveBeenCalled() + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/index.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/index.spec.js new file mode 100644 index 00000000..9e154818 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/index.spec.js @@ -0,0 +1,720 @@ +import * as Util from '../../../src/util/index.js' +import { noop } from '../../../src/util/index.js' +import { clearFixture, getFixture } from '../../helpers/fixture.js' + +describe('Util', () => { + let fixtureEl + + beforeAll(() => { + fixtureEl = getFixture() + }) + + afterEach(() => { + clearFixture() + }) + + describe('getUID', () => { + it('should generate uid', () => { + const uid = Util.getUID('bs') + const uid2 = Util.getUID('bs') + + expect(uid).not.toEqual(uid2) + }) + }) + + describe('getTransitionDurationFromElement', () => { + it('should get transition from element', () => { + fixtureEl.innerHTML = '
    ' + + expect(Util.getTransitionDurationFromElement(fixtureEl.querySelector('div'))).toEqual(300) + }) + + it('should return 0 if the element is undefined or null', () => { + expect(Util.getTransitionDurationFromElement(null)).toEqual(0) + expect(Util.getTransitionDurationFromElement(undefined)).toEqual(0) + }) + + it('should return 0 if the element do not possess transition', () => { + fixtureEl.innerHTML = '
    ' + + expect(Util.getTransitionDurationFromElement(fixtureEl.querySelector('div'))).toEqual(0) + }) + }) + + describe('triggerTransitionEnd', () => { + it('should trigger transitionend event', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '
    ' + + const el = fixtureEl.querySelector('div') + const spy = spyOn(el, 'dispatchEvent').and.callThrough() + + el.addEventListener('transitionend', () => { + expect(spy).toHaveBeenCalled() + resolve() + }) + + Util.triggerTransitionEnd(el) + }) + }) + }) + + describe('isElement', () => { + it('should detect if the parameter is an element or not and return Boolean', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ' + ].join('') + + const el = fixtureEl.querySelector('#foo') + + expect(Util.isElement(el)).toBeTrue() + expect(Util.isElement({})).toBeFalse() + expect(Util.isElement(fixtureEl.querySelectorAll('.test'))).toBeFalse() + }) + + it('should detect jQuery element', () => { + fixtureEl.innerHTML = '
    ' + + const el = fixtureEl.querySelector('div') + const fakejQuery = { + 0: el, + jquery: 'foo' + } + + expect(Util.isElement(fakejQuery)).toBeTrue() + }) + }) + + describe('getElement', () => { + it('should try to parse element', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ' + ].join('') + + const el = fixtureEl.querySelector('div') + + expect(Util.getElement(el)).toEqual(el) + expect(Util.getElement('#foo')).toEqual(el) + expect(Util.getElement('#fail')).toBeNull() + expect(Util.getElement({})).toBeNull() + expect(Util.getElement([])).toBeNull() + expect(Util.getElement()).toBeNull() + expect(Util.getElement(null)).toBeNull() + expect(Util.getElement(fixtureEl.querySelectorAll('.test'))).toBeNull() + + const fakejQueryObject = { + 0: el, + jquery: 'foo' + } + + expect(Util.getElement(fakejQueryObject)).toEqual(el) + }) + }) + + describe('isVisible', () => { + it('should return false if the element is not defined', () => { + expect(Util.isVisible(null)).toBeFalse() + expect(Util.isVisible(undefined)).toBeFalse() + }) + + it('should return false if the element provided is not a dom element', () => { + expect(Util.isVisible({})).toBeFalse() + }) + + it('should return false if the element is not visible with display none', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Util.isVisible(div)).toBeFalse() + }) + + it('should return false if the element is not visible with visibility hidden', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + expect(Util.isVisible(div)).toBeFalse() + }) + + it('should return false if an ancestor element is display none', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('.content') + + expect(Util.isVisible(div)).toBeFalse() + }) + + it('should return false if an ancestor element is visibility hidden', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('.content') + + expect(Util.isVisible(div)).toBeFalse() + }) + + it('should return true if an ancestor element is visibility hidden, but reverted', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('.content') + + expect(Util.isVisible(div)).toBeTrue() + }) + + it('should return true if the element is visible', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#element') + + expect(Util.isVisible(div)).toBeTrue() + }) + + it('should return false if the element is hidden, but not via display or visibility', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#element') + + expect(Util.isVisible(div)).toBeFalse() + }) + + it('should return true if its a closed details element', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('#element') + + expect(Util.isVisible(div)).toBeTrue() + }) + + it('should return true if the element is visible inside an open details element', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#element') + + expect(Util.isVisible(div)).toBeTrue() + }) + + it('should return true if the element is a visible summary in a closed details element', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + ' ', + '
    ' + ].join('') + + const element1 = fixtureEl.querySelector('#element-1') + const element2 = fixtureEl.querySelector('#element-2') + + expect(Util.isVisible(element1)).toBeTrue() + expect(Util.isVisible(element2)).toBeTrue() + }) + }) + + describe('isDisabled', () => { + it('should return true if the element is not defined', () => { + expect(Util.isDisabled(null)).toBeTrue() + expect(Util.isDisabled(undefined)).toBeTrue() + expect(Util.isDisabled()).toBeTrue() + }) + + it('should return true if the element provided is not a dom element', () => { + expect(Util.isDisabled({})).toBeTrue() + expect(Util.isDisabled('test')).toBeTrue() + }) + + it('should return true if the element has disabled attribute', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#element') + const div1 = fixtureEl.querySelector('#element1') + const div2 = fixtureEl.querySelector('#element2') + + expect(Util.isDisabled(div)).toBeTrue() + expect(Util.isDisabled(div1)).toBeTrue() + expect(Util.isDisabled(div2)).toBeTrue() + }) + + it('should return false if the element has disabled attribute with "false" value, or doesn\'t have attribute', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#element') + const div1 = fixtureEl.querySelector('#element1') + + expect(Util.isDisabled(div)).toBeFalse() + expect(Util.isDisabled(div1)).toBeFalse() + }) + + it('should return false if the element is not disabled ', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + ' ', + '
    ' + ].join('') + + const el = selector => fixtureEl.querySelector(selector) + + expect(Util.isDisabled(el('#button'))).toBeFalse() + expect(Util.isDisabled(el('#select'))).toBeFalse() + expect(Util.isDisabled(el('#input'))).toBeFalse() + }) + + it('should return true if the element has disabled attribute', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + '
    ' + ].join('') + + const el = selector => fixtureEl.querySelector(selector) + + expect(Util.isDisabled(el('#input'))).toBeTrue() + expect(Util.isDisabled(el('#input1'))).toBeTrue() + expect(Util.isDisabled(el('#button'))).toBeTrue() + expect(Util.isDisabled(el('#button1'))).toBeTrue() + expect(Util.isDisabled(el('#button2'))).toBeTrue() + expect(Util.isDisabled(el('#input'))).toBeTrue() + }) + + it('should return true if the element has class "disabled"', () => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#element') + + expect(Util.isDisabled(div)).toBeTrue() + }) + + it('should return true if the element has class "disabled" but disabled attribute is false', () => { + fixtureEl.innerHTML = [ + '
    ', + ' ', + '
    ' + ].join('') + + const div = fixtureEl.querySelector('#input') + + expect(Util.isDisabled(div)).toBeTrue() + }) + }) + + describe('findShadowRoot', () => { + it('should return null if shadow dom is not available', () => { + // Only for newer browsers + if (!document.documentElement.attachShadow) { + expect().nothing() + return + } + + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + + spyOn(document.documentElement, 'attachShadow').and.returnValue(null) + + expect(Util.findShadowRoot(div)).toBeNull() + }) + + it('should return null when we do not find a shadow root', () => { + // Only for newer browsers + if (!document.documentElement.attachShadow) { + expect().nothing() + return + } + + spyOn(document, 'getRootNode').and.returnValue(undefined) + + expect(Util.findShadowRoot(document)).toBeNull() + }) + + it('should return the shadow root when found', () => { + // Only for newer browsers + if (!document.documentElement.attachShadow) { + expect().nothing() + return + } + + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const shadowRoot = div.attachShadow({ + mode: 'open' + }) + + expect(Util.findShadowRoot(shadowRoot)).toEqual(shadowRoot) + + shadowRoot.innerHTML = '' + + expect(Util.findShadowRoot(shadowRoot.firstChild)).toEqual(shadowRoot) + }) + }) + + describe('noop', () => { + it('should be a function', () => { + expect(Util.noop).toEqual(jasmine.any(Function)) + }) + }) + + describe('reflow', () => { + it('should return element offset height to force the reflow', () => { + fixtureEl.innerHTML = '
    ' + + const div = fixtureEl.querySelector('div') + const spy = spyOnProperty(div, 'offsetHeight') + Util.reflow(div) + expect(spy).toHaveBeenCalled() + }) + }) + + describe('getjQuery', () => { + const fakejQuery = { trigger() {} } + + beforeEach(() => { + Object.defineProperty(window, 'jQuery', { + value: fakejQuery, + writable: true + }) + }) + + afterEach(() => { + window.jQuery = undefined + }) + + it('should return jQuery object when present', () => { + expect(Util.getjQuery()).toEqual(fakejQuery) + }) + + it('should not return jQuery object when present if data-bs-no-jquery', () => { + document.body.setAttribute('data-bs-no-jquery', '') + + expect(window.jQuery).toEqual(fakejQuery) + expect(Util.getjQuery()).toBeNull() + + document.body.removeAttribute('data-bs-no-jquery') + }) + + it('should not return jQuery if not present', () => { + window.jQuery = undefined + expect(Util.getjQuery()).toBeNull() + }) + }) + + describe('onDOMContentLoaded', () => { + it('should execute callbacks when DOMContentLoaded is fired and should not add more than one listener', () => { + const spy = jasmine.createSpy() + const spy2 = jasmine.createSpy() + + const spyAdd = spyOn(document, 'addEventListener').and.callThrough() + spyOnProperty(document, 'readyState').and.returnValue('loading') + + Util.onDOMContentLoaded(spy) + Util.onDOMContentLoaded(spy2) + + document.dispatchEvent(new Event('DOMContentLoaded', { + bubbles: true, + cancelable: true + })) + + expect(spy).toHaveBeenCalled() + expect(spy2).toHaveBeenCalled() + expect(spyAdd).toHaveBeenCalledTimes(1) + }) + + it('should execute callback if readyState is not "loading"', () => { + const spy = jasmine.createSpy() + Util.onDOMContentLoaded(spy) + expect(spy).toHaveBeenCalled() + }) + }) + + describe('defineJQueryPlugin', () => { + const fakejQuery = { fn: {} } + + beforeEach(() => { + Object.defineProperty(window, 'jQuery', { + value: fakejQuery, + writable: true + }) + }) + + afterEach(() => { + window.jQuery = undefined + }) + + it('should define a plugin on the jQuery instance', () => { + const pluginMock = Util.noop + pluginMock.NAME = 'test' + pluginMock.jQueryInterface = Util.noop + + Util.defineJQueryPlugin(pluginMock) + expect(fakejQuery.fn.test).toEqual(pluginMock.jQueryInterface) + expect(fakejQuery.fn.test.Constructor).toEqual(pluginMock) + expect(fakejQuery.fn.test.noConflict).toEqual(jasmine.any(Function)) + }) + }) + + describe('execute', () => { + it('should execute if arg is function', () => { + const spy = jasmine.createSpy('spy') + Util.execute(spy) + expect(spy).toHaveBeenCalled() + }) + + it('should execute if arg is function & return the result', () => { + const functionFoo = (num1, num2 = 10) => num1 + num2 + const resultFoo = Util.execute(functionFoo, [undefined, 4, 5]) + expect(resultFoo).toBe(9) + + const resultFoo1 = Util.execute(functionFoo, [undefined, 4]) + expect(resultFoo1).toBe(14) + + const functionBar = () => 'foo' + const resultBar = Util.execute(functionBar) + expect(resultBar).toBe('foo') + }) + + it('should not execute if arg is not function & return default argument', () => { + const foo = 'bar' + expect(Util.execute(foo)).toBe('bar') + expect(Util.execute(foo, [], 4)).toBe(4) + }) + }) + + describe('executeAfterTransition', () => { + it('should immediately execute a function when waitForTransition parameter is false', () => { + const el = document.createElement('div') + const callbackSpy = jasmine.createSpy('callback spy') + const eventListenerSpy = spyOn(el, 'addEventListener') + + Util.executeAfterTransition(callbackSpy, el, false) + + expect(callbackSpy).toHaveBeenCalled() + expect(eventListenerSpy).not.toHaveBeenCalled() + }) + + it('should execute a function when a transitionend event is dispatched', () => { + const el = document.createElement('div') + const callbackSpy = jasmine.createSpy('callback spy') + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.05s', + transitionDelay: '0s' + }) + + Util.executeAfterTransition(callbackSpy, el) + + el.dispatchEvent(new TransitionEvent('transitionend')) + + expect(callbackSpy).toHaveBeenCalled() + }) + + it('should execute a function after a computed CSS transition duration and there was no transitionend event dispatched', () => { + return new Promise(resolve => { + const el = document.createElement('div') + const callbackSpy = jasmine.createSpy('callback spy') + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.05s', + transitionDelay: '0s' + }) + + Util.executeAfterTransition(callbackSpy, el) + + setTimeout(() => { + expect(callbackSpy).toHaveBeenCalled() + resolve() + }, 70) + }) + }) + + it('should not execute a function a second time after a computed CSS transition duration and if a transitionend event has already been dispatched', () => { + return new Promise(resolve => { + const el = document.createElement('div') + const callbackSpy = jasmine.createSpy('callback spy') + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.05s', + transitionDelay: '0s' + }) + + Util.executeAfterTransition(callbackSpy, el) + + setTimeout(() => { + el.dispatchEvent(new TransitionEvent('transitionend')) + }, 50) + + setTimeout(() => { + expect(callbackSpy).toHaveBeenCalledTimes(1) + resolve() + }, 70) + }) + }) + + it('should not trigger a transitionend event if another transitionend event had already happened', () => { + return new Promise(resolve => { + const el = document.createElement('div') + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.05s', + transitionDelay: '0s' + }) + + Util.executeAfterTransition(noop, el) + + // simulate a event dispatched by the browser + el.dispatchEvent(new TransitionEvent('transitionend')) + + const dispatchSpy = spyOn(el, 'dispatchEvent').and.callThrough() + + setTimeout(() => { + // setTimeout should not have triggered another transitionend event. + expect(dispatchSpy).not.toHaveBeenCalled() + resolve() + }, 70) + }) + }) + + it('should ignore transitionend events from nested elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '
    ', + '
    ', + '
    ' + ].join('') + + const outer = fixtureEl.querySelector('.outer') + const nested = fixtureEl.querySelector('.nested') + const callbackSpy = jasmine.createSpy('callback spy') + + spyOn(window, 'getComputedStyle').and.returnValue({ + transitionDuration: '0.05s', + transitionDelay: '0s' + }) + + Util.executeAfterTransition(callbackSpy, outer) + + nested.dispatchEvent(new TransitionEvent('transitionend', { + bubbles: true + })) + + setTimeout(() => { + expect(callbackSpy).not.toHaveBeenCalled() + }, 20) + + setTimeout(() => { + expect(callbackSpy).toHaveBeenCalled() + resolve() + }, 70) + }) + }) + }) + + describe('getNextActiveElement', () => { + it('should return first element if active not exists or not given and shouldGetNext is either true, or false with cycling being disabled', () => { + const array = ['a', 'b', 'c', 'd'] + + expect(Util.getNextActiveElement(array, '', true, true)).toEqual('a') + expect(Util.getNextActiveElement(array, 'g', true, true)).toEqual('a') + expect(Util.getNextActiveElement(array, '', true, false)).toEqual('a') + expect(Util.getNextActiveElement(array, 'g', true, false)).toEqual('a') + expect(Util.getNextActiveElement(array, '', false, false)).toEqual('a') + expect(Util.getNextActiveElement(array, 'g', false, false)).toEqual('a') + }) + + it('should return last element if active not exists or not given and shouldGetNext is false but cycling is enabled', () => { + const array = ['a', 'b', 'c', 'd'] + + expect(Util.getNextActiveElement(array, '', false, true)).toEqual('d') + expect(Util.getNextActiveElement(array, 'g', false, true)).toEqual('d') + }) + + it('should return next element or same if is last', () => { + const array = ['a', 'b', 'c', 'd'] + + expect(Util.getNextActiveElement(array, 'a', true, true)).toEqual('b') + expect(Util.getNextActiveElement(array, 'b', true, true)).toEqual('c') + expect(Util.getNextActiveElement(array, 'd', true, false)).toEqual('d') + }) + + it('should return next element or first, if is last and "isCycleAllowed = true"', () => { + const array = ['a', 'b', 'c', 'd'] + + expect(Util.getNextActiveElement(array, 'c', true, true)).toEqual('d') + expect(Util.getNextActiveElement(array, 'd', true, true)).toEqual('a') + }) + + it('should return previous element or same if is first', () => { + const array = ['a', 'b', 'c', 'd'] + + expect(Util.getNextActiveElement(array, 'b', false, true)).toEqual('a') + expect(Util.getNextActiveElement(array, 'd', false, true)).toEqual('c') + expect(Util.getNextActiveElement(array, 'a', false, false)).toEqual('a') + }) + + it('should return next element or first, if is last and "isCycleAllowed = true"', () => { + const array = ['a', 'b', 'c', 'd'] + + expect(Util.getNextActiveElement(array, 'd', false, true)).toEqual('c') + expect(Util.getNextActiveElement(array, 'a', false, true)).toEqual('d') + }) + }) +}) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/sanitizer.spec.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/sanitizer.spec.js new file mode 100644 index 00000000..2b21ef2e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/unit/util/sanitizer.spec.js @@ -0,0 +1,163 @@ +import { DefaultAllowlist, sanitizeHtml } from '../../../src/util/sanitizer.js' + +describe('Sanitizer', () => { + describe('sanitizeHtml', () => { + it('should return the same on empty string', () => { + const empty = '' + + const result = sanitizeHtml(empty, DefaultAllowlist, null) + + expect(result).toEqual(empty) + }) + + it('should retain tags with valid URLs', () => { + const validUrls = [ + '', + 'http://abc', + 'HTTP://abc', + 'https://abc', + 'HTTPS://abc', + 'ftp://abc', + 'FTP://abc', + 'mailto:me@example.com', + 'MAILTO:me@example.com', + 'tel:123-123-1234', + 'TEL:123-123-1234', + 'sip:me@example.com', + 'SIP:me@example.com', + '#anchor', + '/page1.md', + 'http://JavaScript/my.js', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated. + 'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', + 'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', + 'unknown-scheme:abc' + ] + + for (const url of validUrls) { + const template = [ + '
    ', + ` Click me`, + ' Some content', + '
    ' + ].join('') + + const result = sanitizeHtml(template, DefaultAllowlist, null) + + expect(result).toContain(`href="${url}"`) + } + }) + + it('should sanitize template by removing tags with XSS', () => { + const invalidUrls = [ + // eslint-disable-next-line no-script-url + 'javascript:alert(7)', + // eslint-disable-next-line no-script-url + 'javascript:evil()', + // eslint-disable-next-line no-script-url + 'JavaScript:abc', + ' javascript:abc', + ' \n Java\n Script:abc', + 'javascript:', + 'javascript:', + 'j avascript:', + 'javascript:', + 'javascript:', + 'jav ascript:alert();', + 'jav\u0000ascript:alert();' + ] + + for (const url of invalidUrls) { + const template = [ + '
    ', + ` Click me`, + ' Some content', + '
    ' + ].join('') + + const result = sanitizeHtml(template, DefaultAllowlist, null) + + expect(result).not.toContain(`href="${url}"`) + } + }) + + it('should sanitize template and work with multiple regex', () => { + const template = [ + '
    ', + ' Click me', + ' Some content', + '
    ' + ].join('') + + const myDefaultAllowList = DefaultAllowlist + // With the default allow list + let result = sanitizeHtml(template, myDefaultAllowList, null) + + // `data-foo` won't be present + expect(result).not.toContain('data-foo="bar"') + + // Add the following regex too + myDefaultAllowList['*'].push(/^data-foo/) + + result = sanitizeHtml(template, myDefaultAllowList, null) + + expect(result).not.toContain('href="javascript:alert(7)') // This is in the default list + expect(result).toContain('aria-label="This is a link"') // This is in the default list + expect(result).toContain('data-foo="bar"') // We explicitly allow this + }) + + it('should allow aria attributes and safe attributes', () => { + const template = [ + '
    ', + ' Some content', + '
    ' + ].join('') + + const result = sanitizeHtml(template, DefaultAllowlist, null) + + expect(result).toContain('aria-pressed') + expect(result).toContain('class="test"') + }) + + it('should remove tags not in allowlist', () => { + const template = [ + '
    ', + ' ', + '
    ' + ].join('') + + const result = sanitizeHtml(template, DefaultAllowlist, null) + + expect(result).not.toContain(' + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/button.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/button.html new file mode 100644 index 00000000..47c50889 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/button.html @@ -0,0 +1,49 @@ + + + + + + + Button + + +
    +

    Button Bootstrap Visual Test

    + + + +

    For checkboxes and radio buttons, ensure that keyboard behavior is functioning correctly.

    +

    Navigate to the checkboxes with the keyboard (generally, using Tab / Shift + Tab), and ensure that Space toggles the currently focused checkbox. Click on one of the checkboxes using the mouse, ensure that focus was correctly set on the actual checkbox, and that Space toggles the checkbox again.

    + +
    + + + +
    + +

    Navigate to the radio button group with the keyboard (generally, using Tab / Shift + Tab). If no radio button was initially set to be selected, the first/last radio button should receive focus (depending on whether you navigated "forward" to the group with Tab or "backwards" using Shift + Tab). If a radio button was already selected, navigating with the keyboard should set focus to that particular radio button. Only one radio button in a group should receive focus at any given time. Ensure that the selected radio button can be changed by using the and arrow keys. Click on one of the radio buttons with the mouse, ensure that focus was correctly set on the actual radio button, and that and change the selected radio button again.

    + +
    + + + +
    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/carousel.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/carousel.html new file mode 100644 index 00000000..1b2de529 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/carousel.html @@ -0,0 +1,65 @@ + + + + + + + Carousel + + + +
    +

    Carousel Bootstrap Visual Test

    + +

    The transition duration should be around 2s. Also, the carousel shouldn't slide when its window/tab is hidden. Check the console log.

    + + +
    + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/collapse.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/collapse.html new file mode 100644 index 00000000..2782c56b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/collapse.html @@ -0,0 +1,76 @@ + + + + + + + Collapse + + +
    +

    Collapse Bootstrap Visual Test

    + +
    + + + + +
    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/dropdown.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/dropdown.html new file mode 100644 index 00000000..04cf06d7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/dropdown.html @@ -0,0 +1,205 @@ + + + + + + + Dropdown + + +
    +

    Dropdown Bootstrap Visual Test

    + + + + + +
    +
    + +
    + + + +
    +
    + +
    + + +
    + + +
    +
    + +
    +
    + Dropup split align end + + +
    +
    + + +
    +
    + +
    +
    + Dropend split + + +
    +
    + + +
    + +
    + Dropstart split + + +
    +
    + + +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/floating-label.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/floating-label.html new file mode 100644 index 00000000..debecd7e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/floating-label.html @@ -0,0 +1,393 @@ + + + + + + + Form + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/input.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/input.html new file mode 100644 index 00000000..1e5eec2d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/input.html @@ -0,0 +1,78 @@ + + + + + + + Form + + + +
    +

    Input Bootstrap Visual Test

    + +

    No layout

    + +
    + Text + +
    +
    + Email + +
    +
    + Number + +
    +
    + Date + +
    + +

    Flex

    + +
    +
    + Text + +
    +
    + Email + +
    +
    + Number + +
    +
    + Date + +
    +
    + +

    Grid

    + +
    +
    + Text + +
    +
    + Email + +
    +
    + Number + +
    +
    + Date + +
    +
    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/modal.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/modal.html new file mode 100644 index 00000000..efb5127b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/modal.html @@ -0,0 +1,279 @@ + + + + + + + Modal + + + + + +
    +

    Modal Bootstrap Visual Test

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

    + + + (See Issue #18365) + +

    + + + +

    + + + + + +

    + + +
    + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/popover.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/popover.html new file mode 100644 index 00000000..73edf998 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/popover.html @@ -0,0 +1,41 @@ + + + + + + + Popover + + +
    +

    Popover Bootstrap Visual Test

    + + + + + + + + + + +
    + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/scrollspy.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/scrollspy.html new file mode 100644 index 00000000..54102847 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/scrollspy.html @@ -0,0 +1,100 @@ + + + + + + + Scrollspy + + + + +
    +

    @fat

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +
    +

    @mdo

    +

    Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard. Freegan beard aliqua cupidatat mcsweeney's vero. Cupidatat four loko nisi, ea helvetica nulla carles. Tattooed cosby sweater food truck, mcsweeney's quis non freegan vinyl. Lo-fi wes anderson +1 sartorial. Carles non aesthetic exercitation quis gentrify. Brooklyn adipisicing craft beer vice keytar deserunt.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +
    +

    one

    +

    Occaecat commodo aliqua delectus. Fap craft beer deserunt skateboard ea. Lomo bicycle rights adipisicing banh mi, velit ea sunt next level locavore single-origin coffee in magna veniam. High life id vinyl, echo park consequat quis aliquip banh mi pitchfork. Vero VHS est adipisicing. Consectetur nisi DIY minim messenger bag. Cred ex in, sustainable delectus consectetur fanny pack iphone.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +
    +

    two

    +

    In incididunt echo park, officia deserunt mcsweeney's proident master cleanse thundercats sapiente veniam. Excepteur VHS elit, proident shoreditch +1 biodiesel laborum craft beer. Single-origin coffee wayfarers irure four loko, cupidatat terry richardson master cleanse. Assumenda you probably haven't heard of them art party fanny pack, tattooed nulla cardigan tempor ad. Proident wolf nesciunt sartorial keffiyeh eu banh mi sustainable. Elit wolf voluptate, lo-fi ea portland before they sold out four loko. Locavore enim nostrud mlkshk brooklyn nesciunt.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +
    +

    three

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Keytar twee blog, culpa messenger bag marfa whatever delectus food truck. Sapiente synth id assumenda. Locavore sed helvetica cliche irony, thundercats you probably haven't heard of them consequat hoodie gluten-free lo-fi fap aliquip. Labore elit placeat before they sold out, terry richardson proident brunch nesciunt quis cosby sweater pariatur keffiyeh ut helvetica artisan. Cardigan craft beer seitan readymade velit. VHS chambray laboris tempor veniam. Anim mollit minim commodo ullamco thundercats.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +
    +

    Présentation

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +

    Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

    +
    +

    Final section

    +

    Ad leggings keytar, brunch id art party dolor labore.

    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tab.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tab.html new file mode 100644 index 00000000..a424175b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tab.html @@ -0,0 +1,223 @@ + + + + + + + Tab + + + +
    +

    Tab Bootstrap Visual Test

    + +

    Tabs without fade

    + + + +
    +
    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +
    +
    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +
    +
    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +
    +
    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +
    +
    + +

    Tabs with fade

    + + + +
    +
    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +
    +
    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +
    +
    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +
    +
    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +
    +
    + +

    Tabs without fade (no initially active pane)

    + + + +
    +
    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +
    +
    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +
    +
    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +
    +
    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +
    +
    + +

    Tabs with fade (no initially active pane)

    + + + +
    +
    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +
    +
    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +

    Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

    +
    +
    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +
    +
    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +
    +
    + +

    Tabs with nav and using links (with fade)

    + + +
    +
    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +
    +
    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +

    Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

    +
    +
    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +

    Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

    +
    +
    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +

    Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.

    +
    +
    + +

    Tabs with list-group (with fade)

    +
    +
    +
    + + + + +
    +
    +
    + +
    +
    +
    + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/toast.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/toast.html new file mode 100644 index 00000000..e64fd1d8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/toast.html @@ -0,0 +1,70 @@ + + + + + + + Toast + + + +
    +

    Toast Bootstrap Visual Test

    + +
    +
    + + +
    +
    +
    + +
    + + + +
    + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tooltip.html b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tooltip.html new file mode 100644 index 00000000..d03d3b3b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tests/visual/tooltip.html @@ -0,0 +1,138 @@ + + + + + + + Tooltip + + + +
    +

    Tooltip Bootstrap Visual Test

    + +

    Tight pants next level keffiyeh you probably haven't heard of them. Photo booth beard raw denim letterpress vegan messenger bag stumptown. Farm-to-table seitan, mcsweeney's fixie sustainable quinoa 8-bit american apparel have a terry richardson vinyl chambray. Beard stumptown, cardigans banh mi lomo thundercats. Tofu biodiesel williamsburg marfa, four loko mcsweeney's cleanse vegan chambray. A really ironic artisan whatever keytar, scenester farm-to-table banksy Austin freegan cred raw denim single-origin coffee viral.

    + +
    + +
    +

    + + + + + +

    +
    +
    +

    + + + + +

    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    Test Selector triggered tooltips
    +
    +
    + + +
    + +
    +
    + +
    +
    +
    + + + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tooltip.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tooltip.js deleted file mode 100644 index c3fe4b06..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/tooltip.js +++ /dev/null @@ -1,514 +0,0 @@ -/* ======================================================================== - * Bootstrap: tooltip.js v3.3.5 - * http://getbootstrap.com/javascript/#tooltip - * Inspired by the original jQuery.tipsy by Jason Frame - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TOOLTIP PUBLIC CLASS DEFINITION - // =============================== - - var Tooltip = function (element, options) { - this.type = null - this.options = null - this.enabled = null - this.timeout = null - this.hoverState = null - this.$element = null - this.inState = null - - this.init('tooltip', element, options) - } - - Tooltip.VERSION = '3.3.5' - - Tooltip.TRANSITION_DURATION = 150 - - Tooltip.DEFAULTS = { - animation: true, - placement: 'top', - selector: false, - template: '', - trigger: 'hover focus', - title: '', - delay: 0, - html: false, - container: false, - viewport: { - selector: 'body', - padding: 0 - } - } - - Tooltip.prototype.init = function (type, element, options) { - this.enabled = true - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) - this.inState = { click: false, hover: false, focus: false } - - if (this.$element[0] instanceof document.constructor && !this.options.selector) { - throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') - } - - var triggers = this.options.trigger.split(' ') - - for (var i = triggers.length; i--;) { - var trigger = triggers[i] - - if (trigger == 'click') { - this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (trigger != 'manual') { - var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' - var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' - - this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) - } - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - Tooltip.prototype.getDefaults = function () { - return Tooltip.DEFAULTS - } - - Tooltip.prototype.getOptions = function (options) { - options = $.extend({}, this.getDefaults(), this.$element.data(), options) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay, - hide: options.delay - } - } - - return options - } - - Tooltip.prototype.getDelegateOptions = function () { - var options = {} - var defaults = this.getDefaults() - - this._options && $.each(this._options, function (key, value) { - if (defaults[key] != value) options[key] = value - }) - - return options - } - - Tooltip.prototype.enter = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true - } - - if (self.tip().hasClass('in') || self.hoverState == 'in') { - self.hoverState = 'in' - return - } - - clearTimeout(self.timeout) - - self.hoverState = 'in' - - if (!self.options.delay || !self.options.delay.show) return self.show() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'in') self.show() - }, self.options.delay.show) - } - - Tooltip.prototype.isInStateTrue = function () { - for (var key in this.inState) { - if (this.inState[key]) return true - } - - return false - } - - Tooltip.prototype.leave = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false - } - - if (self.isInStateTrue()) return - - clearTimeout(self.timeout) - - self.hoverState = 'out' - - if (!self.options.delay || !self.options.delay.hide) return self.hide() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'out') self.hide() - }, self.options.delay.hide) - } - - Tooltip.prototype.show = function () { - var e = $.Event('show.bs.' + this.type) - - if (this.hasContent() && this.enabled) { - this.$element.trigger(e) - - var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) - if (e.isDefaultPrevented() || !inDom) return - var that = this - - var $tip = this.tip() - - var tipId = this.getUID(this.type) - - this.setContent() - $tip.attr('id', tipId) - this.$element.attr('aria-describedby', tipId) - - if (this.options.animation) $tip.addClass('fade') - - var placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - var autoToken = /\s?auto?\s?/i - var autoPlace = autoToken.test(placement) - if (autoPlace) placement = placement.replace(autoToken, '') || 'top' - - $tip - .detach() - .css({ top: 0, left: 0, display: 'block' }) - .addClass(placement) - .data('bs.' + this.type, this) - - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) - this.$element.trigger('inserted.bs.' + this.type) - - var pos = this.getPosition() - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (autoPlace) { - var orgPlacement = placement - var viewportDim = this.getPosition(this.$viewport) - - placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : - placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : - placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : - placement - - $tip - .removeClass(orgPlacement) - .addClass(placement) - } - - var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) - - this.applyPlacement(calculatedOffset, placement) - - var complete = function () { - var prevHoverState = that.hoverState - that.$element.trigger('shown.bs.' + that.type) - that.hoverState = null - - if (prevHoverState == 'out') that.leave(that) - } - - $.support.transition && this.$tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - } - } - - Tooltip.prototype.applyPlacement = function (offset, placement) { - var $tip = this.tip() - var width = $tip[0].offsetWidth - var height = $tip[0].offsetHeight - - // manually read margins because getBoundingClientRect includes difference - var marginTop = parseInt($tip.css('margin-top'), 10) - var marginLeft = parseInt($tip.css('margin-left'), 10) - - // we must check for NaN for ie 8/9 - if (isNaN(marginTop)) marginTop = 0 - if (isNaN(marginLeft)) marginLeft = 0 - - offset.top += marginTop - offset.left += marginLeft - - // $.fn.offset doesn't round pixel values - // so we use setOffset directly with our own function B-0 - $.offset.setOffset($tip[0], $.extend({ - using: function (props) { - $tip.css({ - top: Math.round(props.top), - left: Math.round(props.left) - }) - } - }, offset), 0) - - $tip.addClass('in') - - // check to see if placing tip in new offset caused the tip to resize itself - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (placement == 'top' && actualHeight != height) { - offset.top = offset.top + height - actualHeight - } - - var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) - - if (delta.left) offset.left += delta.left - else offset.top += delta.top - - var isVertical = /top|bottom/.test(placement) - var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight - var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' - - $tip.offset(offset) - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) - } - - Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { - this.arrow() - .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') - .css(isVertical ? 'top' : 'left', '') - } - - Tooltip.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - - $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) - $tip.removeClass('fade in top bottom left right') - } - - Tooltip.prototype.hide = function (callback) { - var that = this - var $tip = $(this.$tip) - var e = $.Event('hide.bs.' + this.type) - - function complete() { - if (that.hoverState != 'in') $tip.detach() - that.$element - .removeAttr('aria-describedby') - .trigger('hidden.bs.' + that.type) - callback && callback() - } - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - $tip.removeClass('in') - - $.support.transition && $tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - - this.hoverState = null - - return this - } - - Tooltip.prototype.fixTitle = function () { - var $e = this.$element - if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') - } - } - - Tooltip.prototype.hasContent = function () { - return this.getTitle() - } - - Tooltip.prototype.getPosition = function ($element) { - $element = $element || this.$element - - var el = $element[0] - var isBody = el.tagName == 'BODY' - - var elRect = el.getBoundingClientRect() - if (elRect.width == null) { - // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 - elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) - } - var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() - var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } - var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null - - return $.extend({}, elRect, scroll, outerDims, elOffset) - } - - Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } - - } - - Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { - var delta = { top: 0, left: 0 } - if (!this.$viewport) return delta - - var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 - var viewportDimensions = this.getPosition(this.$viewport) - - if (/right|left/.test(placement)) { - var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll - var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight - if (topEdgeOffset < viewportDimensions.top) { // top overflow - delta.top = viewportDimensions.top - topEdgeOffset - } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow - delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset - } - } else { - var leftEdgeOffset = pos.left - viewportPadding - var rightEdgeOffset = pos.left + viewportPadding + actualWidth - if (leftEdgeOffset < viewportDimensions.left) { // left overflow - delta.left = viewportDimensions.left - leftEdgeOffset - } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow - delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset - } - } - - return delta - } - - Tooltip.prototype.getTitle = function () { - var title - var $e = this.$element - var o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - return title - } - - Tooltip.prototype.getUID = function (prefix) { - do prefix += ~~(Math.random() * 1000000) - while (document.getElementById(prefix)) - return prefix - } - - Tooltip.prototype.tip = function () { - if (!this.$tip) { - this.$tip = $(this.options.template) - if (this.$tip.length != 1) { - throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') - } - } - return this.$tip - } - - Tooltip.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) - } - - Tooltip.prototype.enable = function () { - this.enabled = true - } - - Tooltip.prototype.disable = function () { - this.enabled = false - } - - Tooltip.prototype.toggleEnabled = function () { - this.enabled = !this.enabled - } - - Tooltip.prototype.toggle = function (e) { - var self = this - if (e) { - self = $(e.currentTarget).data('bs.' + this.type) - if (!self) { - self = new this.constructor(e.currentTarget, this.getDelegateOptions()) - $(e.currentTarget).data('bs.' + this.type, self) - } - } - - if (e) { - self.inState.click = !self.inState.click - if (self.isInStateTrue()) self.enter(self) - else self.leave(self) - } else { - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) - } - } - - Tooltip.prototype.destroy = function () { - var that = this - clearTimeout(this.timeout) - this.hide(function () { - that.$element.off('.' + that.type).removeData('bs.' + that.type) - if (that.$tip) { - that.$tip.detach() - } - that.$tip = null - that.$arrow = null - that.$viewport = null - }) - } - - - // TOOLTIP PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tooltip') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tooltip - - $.fn.tooltip = Plugin - $.fn.tooltip.Constructor = Tooltip - - - // TOOLTIP NO CONFLICT - // =================== - - $.fn.tooltip.noConflict = function () { - $.fn.tooltip = old - return this - } - -}(jQuery); diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/transition.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/transition.js deleted file mode 100644 index cd89fc49..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/js/transition.js +++ /dev/null @@ -1,59 +0,0 @@ -/* ======================================================================== - * Bootstrap: transition.js v3.3.5 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - WebkitTransition : 'webkitTransitionEnd', - MozTransition : 'transitionend', - OTransition : 'oTransitionEnd otransitionend', - transition : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false - var $el = this - $(this).one('bsTransitionEnd', function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - - if (!$.support.transition) return - - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function (e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) - } - } - }) - -}(jQuery); diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csscomb.json b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csscomb.json deleted file mode 100644 index 40695a47..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csscomb.json +++ /dev/null @@ -1,304 +0,0 @@ -{ - "always-semicolon": true, - "block-indent": 2, - "color-case": "lower", - "color-shorthand": true, - "element-case": "lower", - "eof-newline": true, - "leading-zero": false, - "remove-empty-rulesets": true, - "space-after-colon": 1, - "space-after-combinator": 1, - "space-before-selector-delimiter": 0, - "space-between-declarations": "\n", - "space-after-opening-brace": "\n", - "space-before-closing-brace": "\n", - "space-before-colon": 0, - "space-before-combinator": 1, - "space-before-opening-brace": 1, - "strip-spaces": true, - "unitless-zero": true, - "vendor-prefix-align": true, - "sort-order": [ - [ - "position", - "top", - "right", - "bottom", - "left", - "z-index", - "display", - "float", - "width", - "min-width", - "max-width", - "height", - "min-height", - "max-height", - "-webkit-box-sizing", - "-moz-box-sizing", - "box-sizing", - "-webkit-appearance", - "padding", - "padding-top", - "padding-right", - "padding-bottom", - "padding-left", - "margin", - "margin-top", - "margin-right", - "margin-bottom", - "margin-left", - "overflow", - "overflow-x", - "overflow-y", - "-webkit-overflow-scrolling", - "-ms-overflow-x", - "-ms-overflow-y", - "-ms-overflow-style", - "clip", - "clear", - "font", - "font-family", - "font-size", - "font-style", - "font-weight", - "font-variant", - "font-size-adjust", - "font-stretch", - "font-effect", - "font-emphasize", - "font-emphasize-position", - "font-emphasize-style", - "font-smooth", - "-webkit-hyphens", - "-moz-hyphens", - "hyphens", - "line-height", - "color", - "text-align", - "-webkit-text-align-last", - "-moz-text-align-last", - "-ms-text-align-last", - "text-align-last", - "text-emphasis", - "text-emphasis-color", - "text-emphasis-style", - "text-emphasis-position", - "text-decoration", - "text-indent", - "text-justify", - "text-outline", - "-ms-text-overflow", - "text-overflow", - "text-overflow-ellipsis", - "text-overflow-mode", - "text-shadow", - "text-transform", - "text-wrap", - "-webkit-text-size-adjust", - "-ms-text-size-adjust", - "letter-spacing", - "-ms-word-break", - "word-break", - "word-spacing", - "-ms-word-wrap", - "word-wrap", - "-moz-tab-size", - "-o-tab-size", - "tab-size", - "white-space", - "vertical-align", - "list-style", - "list-style-position", - "list-style-type", - "list-style-image", - "pointer-events", - "-ms-touch-action", - "touch-action", - "cursor", - "visibility", - "zoom", - "flex-direction", - "flex-order", - "flex-pack", - "flex-align", - "table-layout", - "empty-cells", - "caption-side", - "border-spacing", - "border-collapse", - "content", - "quotes", - "counter-reset", - "counter-increment", - "resize", - "-webkit-user-select", - "-moz-user-select", - "-ms-user-select", - "-o-user-select", - "user-select", - "nav-index", - "nav-up", - "nav-right", - "nav-down", - "nav-left", - "background", - "background-color", - "background-image", - "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", - "filter:progid:DXImageTransform.Microsoft.gradient", - "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", - "filter", - "background-repeat", - "background-attachment", - "background-position", - "background-position-x", - "background-position-y", - "-webkit-background-clip", - "-moz-background-clip", - "background-clip", - "background-origin", - "-webkit-background-size", - "-moz-background-size", - "-o-background-size", - "background-size", - "border", - "border-color", - "border-style", - "border-width", - "border-top", - "border-top-color", - "border-top-style", - "border-top-width", - "border-right", - "border-right-color", - "border-right-style", - "border-right-width", - "border-bottom", - "border-bottom-color", - "border-bottom-style", - "border-bottom-width", - "border-left", - "border-left-color", - "border-left-style", - "border-left-width", - "border-radius", - "border-top-left-radius", - "border-top-right-radius", - "border-bottom-right-radius", - "border-bottom-left-radius", - "-webkit-border-image", - "-moz-border-image", - "-o-border-image", - "border-image", - "-webkit-border-image-source", - "-moz-border-image-source", - "-o-border-image-source", - "border-image-source", - "-webkit-border-image-slice", - "-moz-border-image-slice", - "-o-border-image-slice", - "border-image-slice", - "-webkit-border-image-width", - "-moz-border-image-width", - "-o-border-image-width", - "border-image-width", - "-webkit-border-image-outset", - "-moz-border-image-outset", - "-o-border-image-outset", - "border-image-outset", - "-webkit-border-image-repeat", - "-moz-border-image-repeat", - "-o-border-image-repeat", - "border-image-repeat", - "outline", - "outline-width", - "outline-style", - "outline-color", - "outline-offset", - "-webkit-box-shadow", - "-moz-box-shadow", - "box-shadow", - "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", - "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", - "opacity", - "-ms-interpolation-mode", - "-webkit-transition", - "-moz-transition", - "-ms-transition", - "-o-transition", - "transition", - "-webkit-transition-delay", - "-moz-transition-delay", - "-ms-transition-delay", - "-o-transition-delay", - "transition-delay", - "-webkit-transition-timing-function", - "-moz-transition-timing-function", - "-ms-transition-timing-function", - "-o-transition-timing-function", - "transition-timing-function", - "-webkit-transition-duration", - "-moz-transition-duration", - "-ms-transition-duration", - "-o-transition-duration", - "transition-duration", - "-webkit-transition-property", - "-moz-transition-property", - "-ms-transition-property", - "-o-transition-property", - "transition-property", - "-webkit-transform", - "-moz-transform", - "-ms-transform", - "-o-transform", - "transform", - "-webkit-transform-origin", - "-moz-transform-origin", - "-ms-transform-origin", - "-o-transform-origin", - "transform-origin", - "-webkit-animation", - "-moz-animation", - "-ms-animation", - "-o-animation", - "animation", - "-webkit-animation-name", - "-moz-animation-name", - "-ms-animation-name", - "-o-animation-name", - "animation-name", - "-webkit-animation-duration", - "-moz-animation-duration", - "-ms-animation-duration", - "-o-animation-duration", - "animation-duration", - "-webkit-animation-play-state", - "-moz-animation-play-state", - "-ms-animation-play-state", - "-o-animation-play-state", - "animation-play-state", - "-webkit-animation-timing-function", - "-moz-animation-timing-function", - "-ms-animation-timing-function", - "-o-animation-timing-function", - "animation-timing-function", - "-webkit-animation-delay", - "-moz-animation-delay", - "-ms-animation-delay", - "-o-animation-delay", - "animation-delay", - "-webkit-animation-iteration-count", - "-moz-animation-iteration-count", - "-ms-animation-iteration-count", - "-o-animation-iteration-count", - "animation-iteration-count", - "-webkit-animation-direction", - "-moz-animation-direction", - "-ms-animation-direction", - "-o-animation-direction", - "animation-direction" - ] - ] -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csslintrc b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csslintrc deleted file mode 100644 index 005b8623..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/.csslintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "adjoining-classes": false, - "box-sizing": false, - "box-model": false, - "compatible-vendor-prefixes": false, - "floats": false, - "font-sizes": false, - "gradients": false, - "important": false, - "known-properties": false, - "outline-none": false, - "qualified-headings": false, - "regex-selectors": false, - "shorthand": false, - "text-indent": false, - "unique-headings": false, - "universal-selector": false, - "unqualified-attributes": false -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/alerts.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/alerts.less deleted file mode 100644 index c4199db9..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/alerts.less +++ /dev/null @@ -1,73 +0,0 @@ -// -// Alerts -// -------------------------------------------------- - - -// Base styles -// ------------------------- - -.alert { - padding: @alert-padding; - margin-bottom: @line-height-computed; - border: 1px solid transparent; - border-radius: @alert-border-radius; - - // Headings for larger alerts - h4 { - margin-top: 0; - // Specified for the h4 to prevent conflicts of changing @headings-color - color: inherit; - } - - // Provide class for links that match alerts - .alert-link { - font-weight: @alert-link-font-weight; - } - - // Improve alignment and spacing of inner content - > p, - > ul { - margin-bottom: 0; - } - - > p + p { - margin-top: 5px; - } -} - -// Dismissible alerts -// -// Expand the right padding and account for the close button's positioning. - -.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. -.alert-dismissible { - padding-right: (@alert-padding + 20); - - // Adjust close link position - .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; - } -} - -// Alternate styles -// -// Generate contextual modifier classes for colorizing the alert. - -.alert-success { - .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); -} - -.alert-info { - .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); -} - -.alert-warning { - .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); -} - -.alert-danger { - .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/badges.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/badges.less deleted file mode 100644 index 6ee16dca..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/badges.less +++ /dev/null @@ -1,66 +0,0 @@ -// -// Badges -// -------------------------------------------------- - - -// Base class -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: @font-size-small; - font-weight: @badge-font-weight; - color: @badge-color; - line-height: @badge-line-height; - vertical-align: middle; - white-space: nowrap; - text-align: center; - background-color: @badge-bg; - border-radius: @badge-border-radius; - - // Empty badges collapse automatically (not available in IE8) - &:empty { - display: none; - } - - // Quick fix for badges in buttons - .btn & { - position: relative; - top: -1px; - } - - .btn-xs &, - .btn-group-xs > .btn & { - top: 0; - padding: 1px 5px; - } - - // Hover state, but only for links - a& { - &:hover, - &:focus { - color: @badge-link-hover-color; - text-decoration: none; - cursor: pointer; - } - } - - // Account for badges in navs - .list-group-item.active > &, - .nav-pills > .active > a > & { - color: @badge-active-color; - background-color: @badge-active-bg; - } - - .list-group-item > & { - float: right; - } - - .list-group-item > & + & { - margin-right: 5px; - } - - .nav-pills > li > a > & { - margin-left: 3px; - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/bootstrap.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/bootstrap.less deleted file mode 100644 index 4b9916e6..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/bootstrap.less +++ /dev/null @@ -1,56 +0,0 @@ -/*! - * Bootstrap v3.3.5 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -// Core variables and mixins -@import "variables.less"; -@import "mixins.less"; - -// Reset and dependencies -@import "normalize.less"; -@import "print.less"; -@import "glyphicons.less"; - -// Core CSS -@import "scaffolding.less"; -@import "type.less"; -@import "code.less"; -@import "grid.less"; -@import "tables.less"; -@import "forms.less"; -@import "buttons.less"; - -// Components -@import "component-animations.less"; -@import "dropdowns.less"; -@import "button-groups.less"; -@import "input-groups.less"; -@import "navs.less"; -@import "navbar.less"; -@import "breadcrumbs.less"; -@import "pagination.less"; -@import "pager.less"; -@import "labels.less"; -@import "badges.less"; -@import "jumbotron.less"; -@import "thumbnails.less"; -@import "alerts.less"; -@import "progress-bars.less"; -@import "media.less"; -@import "list-group.less"; -@import "panels.less"; -@import "responsive-embed.less"; -@import "wells.less"; -@import "close.less"; - -// Components w/ JavaScript -@import "modals.less"; -@import "tooltip.less"; -@import "popovers.less"; -@import "carousel.less"; - -// Utility classes -@import "utilities.less"; -@import "responsive-utilities.less"; diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/breadcrumbs.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/breadcrumbs.less deleted file mode 100644 index cb01d503..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/breadcrumbs.less +++ /dev/null @@ -1,26 +0,0 @@ -// -// Breadcrumbs -// -------------------------------------------------- - - -.breadcrumb { - padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal; - margin-bottom: @line-height-computed; - list-style: none; - background-color: @breadcrumb-bg; - border-radius: @border-radius-base; - - > li { - display: inline-block; - - + li:before { - content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space - padding: 0 5px; - color: @breadcrumb-color; - } - } - - > .active { - color: @breadcrumb-active-color; - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/button-groups.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/button-groups.less deleted file mode 100644 index 6a0c5a86..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/button-groups.less +++ /dev/null @@ -1,244 +0,0 @@ -// -// Button groups -// -------------------------------------------------- - -// Make the div behave like a button -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; // match .btn alignment given font-size hack above - > .btn { - position: relative; - float: left; - // Bring the "active" button to the front - &:hover, - &:focus, - &:active, - &.active { - z-index: 2; - } - } -} - -// Prevent double borders when buttons are next to each other -.btn-group { - .btn + .btn, - .btn + .btn-group, - .btn-group + .btn, - .btn-group + .btn-group { - margin-left: -1px; - } -} - -// Optional: Group multiple button groups together for a toolbar -.btn-toolbar { - margin-left: -5px; // Offset the first child's margin - &:extend(.clearfix all); - - .btn, - .btn-group, - .input-group { - float: left; - } - > .btn, - > .btn-group, - > .input-group { - margin-left: 5px; - } -} - -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} - -// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match -.btn-group > .btn:first-child { - margin-left: 0; - &:not(:last-child):not(.dropdown-toggle) { - .border-right-radius(0); - } -} -// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - .border-left-radius(0); -} - -// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) -.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, - > .dropdown-toggle { - .border-right-radius(0); - } -} -.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { - .border-left-radius(0); -} - -// On active and open, don't show outline -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - - -// Sizing -// -// Remix the default button sizing classes into new ones for easier manipulation. - -.btn-group-xs > .btn { &:extend(.btn-xs); } -.btn-group-sm > .btn { &:extend(.btn-sm); } -.btn-group-lg > .btn { &:extend(.btn-lg); } - - -// Split button dropdowns -// ---------------------- - -// Give the line between buttons some depth -.btn-group > .btn + .dropdown-toggle { - padding-left: 8px; - padding-right: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-left: 12px; - padding-right: 12px; -} - -// The clickable button for toggling the menu -// Remove the gradient and set the same inset shadow as the :active state -.btn-group.open .dropdown-toggle { - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - - // Show no shadow for `.btn-link` since it has no other button styles. - &.btn-link { - .box-shadow(none); - } -} - - -// Reposition the caret -.btn .caret { - margin-left: 0; -} -// Carets in other button sizes -.btn-lg .caret { - border-width: @caret-width-large @caret-width-large 0; - border-bottom-width: 0; -} -// Upside down carets for .dropup -.dropup .btn-lg .caret { - border-width: 0 @caret-width-large @caret-width-large; -} - - -// Vertical button groups -// ---------------------- - -.btn-group-vertical { - > .btn, - > .btn-group, - > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; - } - - // Clear floats so dropdown menus can be properly placed - > .btn-group { - &:extend(.clearfix all); - > .btn { - float: none; - } - } - - > .btn + .btn, - > .btn + .btn-group, - > .btn-group + .btn, - > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; - } -} - -.btn-group-vertical > .btn { - &:not(:first-child):not(:last-child) { - border-radius: 0; - } - &:first-child:not(:last-child) { - border-top-right-radius: @btn-border-radius-base; - .border-bottom-radius(0); - } - &:last-child:not(:first-child) { - border-bottom-left-radius: @btn-border-radius-base; - .border-top-radius(0); - } -} -.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, - > .dropdown-toggle { - .border-bottom-radius(0); - } -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - .border-top-radius(0); -} - - -// Justified button groups -// ---------------------- - -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; - > .btn, - > .btn-group { - float: none; - display: table-cell; - width: 1%; - } - > .btn-group .btn { - width: 100%; - } - - > .btn-group .dropdown-menu { - left: auto; - } -} - - -// Checkbox and radio options -// -// In order to support the browser's form validation feedback, powered by the -// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use -// `display: none;` or `visibility: hidden;` as that also hides the popover. -// Simply visually hiding the inputs via `opacity` would leave them clickable in -// certain cases which is prevented by using `clip` and `pointer-events`. -// This way, we ensure a DOM element is visible to position the popover from. -// -// See https://github.com/twbs/bootstrap/pull/12794 and -// https://github.com/twbs/bootstrap/pull/14559 for more information. - -[data-toggle="buttons"] { - > .btn, - > .btn-group > .btn { - input[type="radio"], - input[type="checkbox"] { - position: absolute; - clip: rect(0,0,0,0); - pointer-events: none; - } - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/buttons.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/buttons.less deleted file mode 100644 index 9cbb8f41..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/buttons.less +++ /dev/null @@ -1,166 +0,0 @@ -// -// Buttons -// -------------------------------------------------- - - -// Base styles -// -------------------------------------------------- - -.btn { - display: inline-block; - margin-bottom: 0; // For input.btn - font-weight: @btn-font-weight; - text-align: center; - vertical-align: middle; - touch-action: manipulation; - cursor: pointer; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid transparent; - white-space: nowrap; - .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base); - .user-select(none); - - &, - &:active, - &.active { - &:focus, - &.focus { - .tab-focus(); - } - } - - &:hover, - &:focus, - &.focus { - color: @btn-default-color; - text-decoration: none; - } - - &:active, - &.active { - outline: 0; - background-image: none; - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - } - - &.disabled, - &[disabled], - fieldset[disabled] & { - cursor: @cursor-disabled; - .opacity(.65); - .box-shadow(none); - } - - a& { - &.disabled, - fieldset[disabled] & { - pointer-events: none; // Future-proof disabling of clicks on `` elements - } - } -} - - -// Alternate buttons -// -------------------------------------------------- - -.btn-default { - .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); -} -.btn-primary { - .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border); -} -// Success appears as green -.btn-success { - .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border); -} -// Info appears as blue-green -.btn-info { - .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border); -} -// Warning appears as orange -.btn-warning { - .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border); -} -// Danger and error appear as red -.btn-danger { - .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border); -} - - -// Link buttons -// ------------------------- - -// Make a button look and behave like a link -.btn-link { - color: @link-color; - font-weight: normal; - border-radius: 0; - - &, - &:active, - &.active, - &[disabled], - fieldset[disabled] & { - background-color: transparent; - .box-shadow(none); - } - &, - &:hover, - &:focus, - &:active { - border-color: transparent; - } - &:hover, - &:focus { - color: @link-hover-color; - text-decoration: @link-hover-decoration; - background-color: transparent; - } - &[disabled], - fieldset[disabled] & { - &:hover, - &:focus { - color: @btn-link-disabled-color; - text-decoration: none; - } - } -} - - -// Button Sizes -// -------------------------------------------------- - -.btn-lg { - // line-height: ensure even-numbered height of button next to large input - .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large); -} -.btn-sm { - // line-height: ensure proper height of button next to small input - .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small); -} -.btn-xs { - .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small); -} - - -// Block button -// -------------------------------------------------- - -.btn-block { - display: block; - width: 100%; -} - -// Vertically space out multiple block buttons -.btn-block + .btn-block { - margin-top: 5px; -} - -// Specificity overrides -input[type="submit"], -input[type="reset"], -input[type="button"] { - &.btn-block { - width: 100%; - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/carousel.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/carousel.less deleted file mode 100644 index 87ed6961..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/carousel.less +++ /dev/null @@ -1,269 +0,0 @@ -// -// Carousel -// -------------------------------------------------- - - -// Wrapper for the slide container and indicators -.carousel { - position: relative; -} - -.carousel-inner { - position: relative; - overflow: hidden; - width: 100%; - - > .item { - display: none; - position: relative; - .transition(.6s ease-in-out left); - - // Account for jankitude on images - > img, - > a > img { - &:extend(.img-responsive); - line-height: 1; - } - - // WebKit CSS3 transforms for supported devices - @media all and (transform-3d), (-webkit-transform-3d) { - .transition-transform(~'0.6s ease-in-out'); - .backface-visibility(~'hidden'); - .perspective(1000px); - - &.next, - &.active.right { - .translate3d(100%, 0, 0); - left: 0; - } - &.prev, - &.active.left { - .translate3d(-100%, 0, 0); - left: 0; - } - &.next.left, - &.prev.right, - &.active { - .translate3d(0, 0, 0); - left: 0; - } - } - } - - > .active, - > .next, - > .prev { - display: block; - } - - > .active { - left: 0; - } - - > .next, - > .prev { - position: absolute; - top: 0; - width: 100%; - } - - > .next { - left: 100%; - } - > .prev { - left: -100%; - } - > .next.left, - > .prev.right { - left: 0; - } - - > .active.left { - left: -100%; - } - > .active.right { - left: 100%; - } - -} - -// Left/right controls for nav -// --------------------------- - -.carousel-control { - position: absolute; - top: 0; - left: 0; - bottom: 0; - width: @carousel-control-width; - .opacity(@carousel-control-opacity); - font-size: @carousel-control-font-size; - color: @carousel-control-color; - text-align: center; - text-shadow: @carousel-text-shadow; - // We can't have this transition here because WebKit cancels the carousel - // animation if you trip this while in the middle of another animation. - - // Set gradients for backgrounds - &.left { - #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001)); - } - &.right { - left: auto; - right: 0; - #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5)); - } - - // Hover/focus state - &:hover, - &:focus { - outline: 0; - color: @carousel-control-color; - text-decoration: none; - .opacity(.9); - } - - // Toggles - .icon-prev, - .icon-next, - .glyphicon-chevron-left, - .glyphicon-chevron-right { - position: absolute; - top: 50%; - margin-top: -10px; - z-index: 5; - display: inline-block; - } - .icon-prev, - .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; - } - .icon-next, - .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; - } - .icon-prev, - .icon-next { - width: 20px; - height: 20px; - line-height: 1; - font-family: serif; - } - - - .icon-prev { - &:before { - content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) - } - } - .icon-next { - &:before { - content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) - } - } -} - -// Optional indicator pips -// -// Add an unordered list with the following class and add a list item for each -// slide your carousel holds. - -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - margin-left: -30%; - padding-left: 0; - list-style: none; - text-align: center; - - li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - border: 1px solid @carousel-indicator-border-color; - border-radius: 10px; - cursor: pointer; - - // IE8-9 hack for event handling - // - // Internet Explorer 8-9 does not support clicks on elements without a set - // `background-color`. We cannot use `filter` since that's not viewed as a - // background color by the browser. Thus, a hack is needed. - // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer - // - // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we - // set alpha transparency for the best results possible. - background-color: #000 \9; // IE8 - background-color: rgba(0,0,0,0); // IE9 - } - .active { - margin: 0; - width: 12px; - height: 12px; - background-color: @carousel-indicator-active-bg; - } -} - -// Optional captions -// ----------------------------- -// Hidden by default for smaller viewports -.carousel-caption { - position: absolute; - left: 15%; - right: 15%; - bottom: 20px; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: @carousel-caption-color; - text-align: center; - text-shadow: @carousel-text-shadow; - & .btn { - text-shadow: none; // No shadow for button elements in carousel-caption - } -} - - -// Scale up controls for tablets and up -@media screen and (min-width: @screen-sm-min) { - - // Scale up the controls a smidge - .carousel-control { - .glyphicon-chevron-left, - .glyphicon-chevron-right, - .icon-prev, - .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - font-size: 30px; - } - .glyphicon-chevron-left, - .icon-prev { - margin-left: -15px; - } - .glyphicon-chevron-right, - .icon-next { - margin-right: -15px; - } - } - - // Show and left align the captions - .carousel-caption { - left: 20%; - right: 20%; - padding-bottom: 30px; - } - - // Move up the indicators - .carousel-indicators { - bottom: 20px; - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/close.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/close.less deleted file mode 100644 index 6d5bfe08..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/close.less +++ /dev/null @@ -1,34 +0,0 @@ -// -// Close icons -// -------------------------------------------------- - - -.close { - float: right; - font-size: (@font-size-base * 1.5); - font-weight: @close-font-weight; - line-height: 1; - color: @close-color; - text-shadow: @close-text-shadow; - .opacity(.2); - - &:hover, - &:focus { - color: @close-color; - text-decoration: none; - cursor: pointer; - .opacity(.5); - } - - // Additional properties for button version - // iOS requires the button element instead of an anchor tag. - // If you want the anchor version, it requires `href="#"`. - // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile - button& { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/code.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/code.less deleted file mode 100644 index a08b4d48..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/code.less +++ /dev/null @@ -1,69 +0,0 @@ -// -// Code (inline and block) -// -------------------------------------------------- - - -// Inline and block code styles -code, -kbd, -pre, -samp { - font-family: @font-family-monospace; -} - -// Inline code -code { - padding: 2px 4px; - font-size: 90%; - color: @code-color; - background-color: @code-bg; - border-radius: @border-radius-base; -} - -// User input typically entered via keyboard -kbd { - padding: 2px 4px; - font-size: 90%; - color: @kbd-color; - background-color: @kbd-bg; - border-radius: @border-radius-small; - box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); - - kbd { - padding: 0; - font-size: 100%; - font-weight: bold; - box-shadow: none; - } -} - -// Blocks of code -pre { - display: block; - padding: ((@line-height-computed - 1) / 2); - margin: 0 0 (@line-height-computed / 2); - font-size: (@font-size-base - 1); // 14px to 13px - line-height: @line-height-base; - word-break: break-all; - word-wrap: break-word; - color: @pre-color; - background-color: @pre-bg; - border: 1px solid @pre-border-color; - border-radius: @border-radius-base; - - // Account for some code outputs that place code tags in pre tags - code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; - } -} - -// Enable scrollable blocks of code -.pre-scrollable { - max-height: @pre-scrollable-max-height; - overflow-y: scroll; -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/component-animations.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/component-animations.less deleted file mode 100644 index 0bcee910..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/component-animations.less +++ /dev/null @@ -1,33 +0,0 @@ -// -// Component animations -// -------------------------------------------------- - -// Heads up! -// -// We don't use the `.opacity()` mixin here since it causes a bug with text -// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. - -.fade { - opacity: 0; - .transition(opacity .15s linear); - &.in { - opacity: 1; - } -} - -.collapse { - display: none; - - &.in { display: block; } - tr&.in { display: table-row; } - tbody&.in { display: table-row-group; } -} - -.collapsing { - position: relative; - height: 0; - overflow: hidden; - .transition-property(~"height, visibility"); - .transition-duration(.35s); - .transition-timing-function(ease); -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/dropdowns.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/dropdowns.less deleted file mode 100644 index f6876c1a..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/dropdowns.less +++ /dev/null @@ -1,216 +0,0 @@ -// -// Dropdown menus -// -------------------------------------------------- - - -// Dropdown arrow/caret -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: @caret-width-base dashed; - border-top: @caret-width-base solid ~"\9"; // IE8 - border-right: @caret-width-base solid transparent; - border-left: @caret-width-base solid transparent; -} - -// The dropdown wrapper (div) -.dropup, -.dropdown { - position: relative; -} - -// Prevent the focus on the dropdown toggle when closing dropdowns -.dropdown-toggle:focus { - outline: 0; -} - -// The dropdown menu (ul) -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: @zindex-dropdown; - display: none; // none by default, but block on "open" of the menu - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; // override default ul - list-style: none; - font-size: @font-size-base; - text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) - background-color: @dropdown-bg; - border: 1px solid @dropdown-fallback-border; // IE8 fallback - border: 1px solid @dropdown-border; - border-radius: @border-radius-base; - .box-shadow(0 6px 12px rgba(0,0,0,.175)); - background-clip: padding-box; - - // Aligns the dropdown menu to right - // - // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` - &.pull-right { - right: 0; - left: auto; - } - - // Dividers (basically an hr) within the dropdown - .divider { - .nav-divider(@dropdown-divider-bg); - } - - // Links within the dropdown menu - > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: @line-height-base; - color: @dropdown-link-color; - white-space: nowrap; // prevent links from randomly breaking onto new lines - } -} - -// Hover/Focus state -.dropdown-menu > li > a { - &:hover, - &:focus { - text-decoration: none; - color: @dropdown-link-hover-color; - background-color: @dropdown-link-hover-bg; - } -} - -// Active state -.dropdown-menu > .active > a { - &, - &:hover, - &:focus { - color: @dropdown-link-active-color; - text-decoration: none; - outline: 0; - background-color: @dropdown-link-active-bg; - } -} - -// Disabled state -// -// Gray out text and ensure the hover/focus state remains gray - -.dropdown-menu > .disabled > a { - &, - &:hover, - &:focus { - color: @dropdown-link-disabled-color; - } - - // Nuke hover/focus effects - &:hover, - &:focus { - text-decoration: none; - background-color: transparent; - background-image: none; // Remove CSS gradient - .reset-filter(); - cursor: @cursor-disabled; - } -} - -// Open state for the dropdown -.open { - // Show the menu - > .dropdown-menu { - display: block; - } - - // Remove the outline when :focus is triggered - > a { - outline: 0; - } -} - -// Menu positioning -// -// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown -// menu with the parent. -.dropdown-menu-right { - left: auto; // Reset the default from `.dropdown-menu` - right: 0; -} -// With v3, we enabled auto-flipping if you have a dropdown within a right -// aligned nav component. To enable the undoing of that, we provide an override -// to restore the default dropdown menu alignment. -// -// This is only for left-aligning a dropdown menu within a `.navbar-right` or -// `.pull-right` nav component. -.dropdown-menu-left { - left: 0; - right: auto; -} - -// Dropdown section headers -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: @font-size-small; - line-height: @line-height-base; - color: @dropdown-header-color; - white-space: nowrap; // as with > li > a -} - -// Backdrop to catch body clicks on mobile, etc. -.dropdown-backdrop { - position: fixed; - left: 0; - right: 0; - bottom: 0; - top: 0; - z-index: (@zindex-dropdown - 10); -} - -// Right aligned dropdowns -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -// Allow for dropdowns to go bottom up (aka, dropup-menu) -// -// Just add .dropup after the standard .dropdown class and you're set, bro. -// TODO: abstract this so that the navbar fixed styles are not placed here? - -.dropup, -.navbar-fixed-bottom .dropdown { - // Reverse the caret - .caret { - border-top: 0; - border-bottom: @caret-width-base dashed; - border-bottom: @caret-width-base solid ~"\9"; // IE8 - content: ""; - } - // Different positioning for bottom up menu - .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; - } -} - - -// Component alignment -// -// Reiterate per navbar.less and the modified component alignment there. - -@media (min-width: @grid-float-breakpoint) { - .navbar-right { - .dropdown-menu { - .dropdown-menu-right(); - } - // Necessary for overrides of the default right aligned menu. - // Will remove come v4 in all likelihood. - .dropdown-menu-left { - .dropdown-menu-left(); - } - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/forms.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/forms.less deleted file mode 100644 index b064ede4..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/forms.less +++ /dev/null @@ -1,607 +0,0 @@ -// -// Forms -// -------------------------------------------------- - - -// Normalize non-controls -// -// Restyle and baseline non-control form elements. - -fieldset { - padding: 0; - margin: 0; - border: 0; - // Chrome and Firefox set a `min-width: min-content;` on fieldsets, - // so we reset that to ensure it behaves more like a standard block element. - // See https://github.com/twbs/bootstrap/issues/12359. - min-width: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: @line-height-computed; - font-size: (@font-size-base * 1.5); - line-height: inherit; - color: @legend-color; - border: 0; - border-bottom: 1px solid @legend-border-color; -} - -label { - display: inline-block; - max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) - margin-bottom: 5px; - font-weight: bold; -} - - -// Normalize form controls -// -// While most of our form styles require extra classes, some basic normalization -// is required to ensure optimum display with or without those classes to better -// address browser inconsistencies. - -// Override content-box in Normalize (* isn't specific enough) -input[type="search"] { - .box-sizing(border-box); -} - -// Position radios and checkboxes better -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; // IE8-9 - line-height: normal; -} - -input[type="file"] { - display: block; -} - -// Make range inputs behave like textual form controls -input[type="range"] { - display: block; - width: 100%; -} - -// Make multiple select elements height not fixed -select[multiple], -select[size] { - height: auto; -} - -// Focus for file, radio, and checkbox -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - .tab-focus(); -} - -// Adjust output element -output { - display: block; - padding-top: (@padding-base-vertical + 1); - font-size: @font-size-base; - line-height: @line-height-base; - color: @input-color; -} - - -// Common form controls -// -// Shared size and type resets for form controls. Apply `.form-control` to any -// of the following form controls: -// -// select -// textarea -// input[type="text"] -// input[type="password"] -// input[type="datetime"] -// input[type="datetime-local"] -// input[type="date"] -// input[type="month"] -// input[type="time"] -// input[type="week"] -// input[type="number"] -// input[type="email"] -// input[type="url"] -// input[type="search"] -// input[type="tel"] -// input[type="color"] - -.form-control { - display: block; - width: 100%; - height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) - padding: @padding-base-vertical @padding-base-horizontal; - font-size: @font-size-base; - line-height: @line-height-base; - color: @input-color; - background-color: @input-bg; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid @input-border; - border-radius: @input-border-radius; // Note: This has no effect on s in CSS. - .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); - .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s"); - - // Customize the `:focus` state to imitate native WebKit styles. - .form-control-focus(); - - // Placeholder - .placeholder(); - - // Disabled and read-only inputs - // - // HTML5 says that controls under a fieldset > legend:first-child won't be - // disabled if the fieldset is disabled. Due to implementation difficulty, we - // don't honor that edge case; we style them as disabled anyway. - &[disabled], - &[readonly], - fieldset[disabled] & { - background-color: @input-bg-disabled; - opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655 - } - - &[disabled], - fieldset[disabled] & { - cursor: @cursor-disabled; - } - - // Reset height for `textarea`s - textarea& { - height: auto; - } -} - - -// Search inputs in iOS -// -// This overrides the extra rounded corners on search inputs in iOS so that our -// `.form-control` class can properly style them. Note that this cannot simply -// be added to `.form-control` as it's not specific enough. For details, see -// https://github.com/twbs/bootstrap/issues/11586. - -input[type="search"] { - -webkit-appearance: none; -} - - -// Special styles for iOS temporal inputs -// -// In Mobile Safari, setting `display: block` on temporal inputs causes the -// text within the input to become vertically misaligned. As a workaround, we -// set a pixel line-height that matches the given height of the input, but only -// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848 -// -// Note that as of 8.3, iOS doesn't support `datetime` or `week`. - -@media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"], - input[type="time"], - input[type="datetime-local"], - input[type="month"] { - &.form-control { - line-height: @input-height-base; - } - - &.input-sm, - .input-group-sm & { - line-height: @input-height-small; - } - - &.input-lg, - .input-group-lg & { - line-height: @input-height-large; - } - } -} - - -// Form groups -// -// Designed to help with the organization and spacing of vertical forms. For -// horizontal forms, use the predefined grid classes. - -.form-group { - margin-bottom: @form-group-margin-bottom; -} - - -// Checkboxes and radios -// -// Indent the labels to position radios/checkboxes as hanging controls. - -.radio, -.checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; - - label { - min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; - } -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-left: -20px; - margin-top: 4px \9; -} - -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing -} - -// Radios and checkboxes on same line -.radio-inline, -.checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - vertical-align: middle; - font-weight: normal; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; // space out consecutive inline controls -} - -// Apply same disabled cursor tweak as for inputs -// Some special care is needed because Star - -// Import the fonts -@font-face { - font-family: 'Glyphicons Halflings'; - src: url('@{icon-font-path}@{icon-font-name}.eot'); - src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'), - url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'), - url('@{icon-font-path}@{icon-font-name}.woff') format('woff'), - url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'), - url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg'); -} - -// Catchall baseclass -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -// Individual icons -.glyphicon-asterisk { &:before { content: "\2a"; } } -.glyphicon-plus { &:before { content: "\2b"; } } -.glyphicon-euro, -.glyphicon-eur { &: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"; } } -// The following 2 Glyphicons are omitted for the time being because -// they currently use Unicode codepoints that are outside the -// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle -// non-BMP codepoints in CSS string escapes, and thus can't display these two icons. -// Notably, the bug affects some older versions of the Android Browser. -// More info: https://github.com/twbs/bootstrap/issues/10106 -// .glyphicon-door { &:before { content: "\1f6aa"; } } -// .glyphicon-key { &:before { content: "\1f511"; } } -.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"; } } diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/grid.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/grid.less deleted file mode 100644 index e100655b..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/grid.less +++ /dev/null @@ -1,84 +0,0 @@ -// -// Grid system -// -------------------------------------------------- - - -// Container widths -// -// Set the container width, and override it for fixed navbars in media queries. - -.container { - .container-fixed(); - - @media (min-width: @screen-sm-min) { - width: @container-sm; - } - @media (min-width: @screen-md-min) { - width: @container-md; - } - @media (min-width: @screen-lg-min) { - width: @container-lg; - } -} - - -// Fluid container -// -// Utilizes the mixin meant for fixed width containers, but without any defined -// width for fluid, full width layouts. - -.container-fluid { - .container-fixed(); -} - - -// Row -// -// Rows contain and clear the floats of your columns. - -.row { - .make-row(); -} - - -// Columns -// -// Common styles for small and large grid columns - -.make-grid-columns(); - - -// Extra small grid -// -// Columns, offsets, pushes, and pulls for extra small devices like -// smartphones. - -.make-grid(xs); - - -// Small grid -// -// Columns, offsets, pushes, and pulls for the small device range, from phones -// to tablets. - -@media (min-width: @screen-sm-min) { - .make-grid(sm); -} - - -// Medium grid -// -// Columns, offsets, pushes, and pulls for the desktop device range. - -@media (min-width: @screen-md-min) { - .make-grid(md); -} - - -// Large grid -// -// Columns, offsets, pushes, and pulls for the large desktop device range. - -@media (min-width: @screen-lg-min) { - .make-grid(lg); -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/input-groups.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/input-groups.less deleted file mode 100644 index 457ea60b..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/input-groups.less +++ /dev/null @@ -1,167 +0,0 @@ -// -// Input groups -// -------------------------------------------------- - -// Base styles -// ------------------------- -.input-group { - position: relative; // For dropdowns - display: table; - border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table - - // Undo padding and float of grid classes - &[class*="col-"] { - float: none; - padding-left: 0; - padding-right: 0; - } - - .form-control { - // Ensure that the input is always above the *appended* addon button for - // proper border colors. - position: relative; - z-index: 2; - - // IE9 fubars the placeholder attribute in text inputs and the arrows on - // select elements in input groups. To fix it, we float the input. Details: - // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855 - float: left; - - width: 100%; - margin-bottom: 0; - } -} - -// Sizing options -// -// Remix the default form control sizing classes into new ones for easier -// manipulation. - -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - .input-lg(); -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - .input-sm(); -} - - -// Display as table-cell -// ------------------------- -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; - - &:not(:first-child):not(:last-child) { - border-radius: 0; - } -} -// Addon and addon wrapper for buttons -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; // Match the inputs -} - -// Text input groups -// ------------------------- -.input-group-addon { - padding: @padding-base-vertical @padding-base-horizontal; - font-size: @font-size-base; - font-weight: normal; - line-height: 1; - color: @input-color; - text-align: center; - background-color: @input-group-addon-bg; - border: 1px solid @input-group-addon-border-color; - border-radius: @border-radius-base; - - // Sizing - &.input-sm { - padding: @padding-small-vertical @padding-small-horizontal; - font-size: @font-size-small; - border-radius: @border-radius-small; - } - &.input-lg { - padding: @padding-large-vertical @padding-large-horizontal; - font-size: @font-size-large; - border-radius: @border-radius-large; - } - - // Nuke default margins from checkboxes and radios to vertically center within. - input[type="radio"], - input[type="checkbox"] { - margin-top: 0; - } -} - -// Reset rounded corners -.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:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - .border-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:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - .border-left-radius(0); -} -.input-group-addon:last-child { - border-left: 0; -} - -// Button input groups -// ------------------------- -.input-group-btn { - position: relative; - // Jankily prevent input button groups from wrapping with `white-space` and - // `font-size` in combination with `inline-block` on buttons. - font-size: 0; - white-space: nowrap; - - // Negative margin for spacing, position for bringing hovered/focused/actived - // element above the siblings. - > .btn { - position: relative; - + .btn { - margin-left: -1px; - } - // Bring the "active" button to the front - &:hover, - &:focus, - &:active { - z-index: 2; - } - } - - // Negative margin to only have a 1px border between the two - &:first-child { - > .btn, - > .btn-group { - margin-right: -1px; - } - } - &:last-child { - > .btn, - > .btn-group { - z-index: 2; - margin-left: -1px; - } - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/jumbotron.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/jumbotron.less deleted file mode 100644 index fa80a38c..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/jumbotron.less +++ /dev/null @@ -1,52 +0,0 @@ -// -// Jumbotron -// -------------------------------------------------- - - -.jumbotron { - padding-top: @jumbotron-padding; - padding-bottom: @jumbotron-padding; - margin-bottom: @jumbotron-padding; - color: @jumbotron-color; - background-color: @jumbotron-bg; - - h1, - .h1 { - color: @jumbotron-heading-color; - } - - p { - margin-bottom: (@jumbotron-padding / 2); - font-size: @jumbotron-font-size; - font-weight: 200; - } - - > hr { - border-top-color: darken(@jumbotron-bg, 10%); - } - - .container &, - .container-fluid & { - border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container - } - - .container { - max-width: 100%; - } - - @media screen and (min-width: @screen-sm-min) { - padding-top: (@jumbotron-padding * 1.6); - padding-bottom: (@jumbotron-padding * 1.6); - - .container &, - .container-fluid & { - padding-left: (@jumbotron-padding * 2); - padding-right: (@jumbotron-padding * 2); - } - - h1, - .h1 { - font-size: @jumbotron-heading-font-size; - } - } -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/labels.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/labels.less deleted file mode 100644 index 9a5a2700..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/labels.less +++ /dev/null @@ -1,64 +0,0 @@ -// -// Labels -// -------------------------------------------------- - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: @label-color; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; - - // Add hover effects, but only for links - a& { - &:hover, - &:focus { - color: @label-link-hover-color; - text-decoration: none; - cursor: pointer; - } - } - - // Empty labels collapse automatically (not available in IE8) - &:empty { - display: none; - } - - // Quick fix for labels in buttons - .btn & { - position: relative; - top: -1px; - } -} - -// Colors -// Contextual variations (linked labels get darker on :hover) - -.label-default { - .label-variant(@label-default-bg); -} - -.label-primary { - .label-variant(@label-primary-bg); -} - -.label-success { - .label-variant(@label-success-bg); -} - -.label-info { - .label-variant(@label-info-bg); -} - -.label-warning { - .label-variant(@label-warning-bg); -} - -.label-danger { - .label-variant(@label-danger-bg); -} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/list-group.less b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/list-group.less deleted file mode 100644 index 216b9123..00000000 --- a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/less/list-group.less +++ /dev/null @@ -1,130 +0,0 @@ -// -// List groups -// -------------------------------------------------- - - -// Base class -// -// Easily usable on + `} /> + + +
  • هذا عنصر في قائمة.
  • +
  • وهذا أيضًا.
  • +
  • لكنهم يظهرون متجاورين.
  • + + `} /> +
    + + +
    +
    +

    الجداول

    + دليل الإستخدام +
    + +
    + + + + # + الاسم الاول + الكنية + الاسم المستعار + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + + + `} /> + + + + + # + الاسم الاول + الكنية + الاسم المستعار + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + + + `} /> + + + + + Class + عنوان + عنوان + + + + + Default + خلية + خلية + `, + ...getData('theme-colors').map((themeColor) => ` + ${themeColor.title} + خلية + خلية + `), + ` + + `]} /> + + + + + # + الاسم الاول + الكنية + الاسم المستعار + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + + + `} /> +
    +
    + + + +
    +

    النماذج

    + +
    +
    +

    نظرة عامة

    + دليل الإستخدام +
    + +
    + +
    + + +
    لن نقوم بمشاركة بريدك الإلكتروني مع أي شخص آخر.
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + أزرار الاختيار الأحادي +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    + + + `} /> +
    +
    +
    +
    +

    الحقول المعطلة

    + دليل الإستخدام +
    + +
    + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    +
    + أزرار اختيار أحادي معطلين +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + `} /> +
    +
    +
    +
    +

    الأحجام

    + دليل الإستخدام +
    + +
    + + +
    +
    + +
    +
    + +
    + `} /> + + + + +
    + +
    +
    + +
    + `} /> + +
    +
    +
    +

    مجموعة الإدخال

    + دليل الإستخدام +
    + +
    + + أنا اسمي + +
    +
    + + وغيرها +
    + +
    + + https://example.com/users/ +
    +
    + .00 + + $ +
    +
    + مع textarea + +
    + `} /> + +
    +
    +
    +

    الحقول ذوي العناوين العائمة

    + دليل الإستخدام +
    + +
    + +
    + + +
    +
    + + +
    + + `} /> +
    +
    +
    +
    +

    التحقق

    + دليل الإستخدام +
    + +
    + +
    + + +
    + يبدو صحيحًا! +
    +
    +
    + + +
    + يبدو صحيحًا! +
    +
    +
    + +
    + + @ +
    + يرجى اختيار اسم مستخدم. +
    +
    +
    +
    + + +
    + يرجى إدخال مدينة صحيحة. +
    +
    +
    + + +
    + يرجى اختيار ولاية صحيحة. +
    +
    +
    + + +
    + يرجى إدخال رمز بريدي صحيح. +
    +
    +
    +
    + + +
    + تجب الموافقة قبل إرسال النموذج. +
    +
    +
    +
    + +
    + + `} /> +
    +
    +
    + +
    +

    العناصر

    + +
    +
    +

    المطوية

    + دليل الإستخدام +
    + +
    + +
    +

    + +

    +
    +
    + هذا هو محتوى عنصر المطوية الأول. سيكون المحتوى مخفيًا بشكل إفتراضي حتى يقوم Bootstrap بإضافة الكلاسات اللازمة لكل عنصر في المطوية. هذه الكلاسات تتحكم بالمظهر العام ووتتحكم أيضا بإظهار وإخفاء أقسام المطوية عبر حركات CSS الإنتقالية. يمكنك تعديل أي من هذه عبر كلاسات CSS خاصة بك، او عبر تغيير القيم الإفتراضية المقدمة من Bootstrap. من الجدير بالذكر أنه يمكن وضع أي كود HTML هنا، ولكن الحركة الإنتقالية قد تحد من الoverflow. +
    +
    +
    +
    +

    + +

    +
    +
    + هذا هو محتوى عنصر المطوية الثاني. سيكون المحتوى مخفيًا بشكل إفتراضي حتى يقوم Bootstrap بإضافة الكلاسات اللازمة لكل عنصر في المطوية. هذه الكلاسات تتحكم بالمظهر العام ووتتحكم أيضا بإظهار وإخفاء أقسام المطوية عبر حركات CSS الإنتقالية. يمكنك تعديل أي من هذه عبر كلاسات CSS خاصة بك، او عبر تغيير القيم الإفتراضية المقدمة من Bootstrap. من الجدير بالذكر أنه يمكن وضع أي كود HTML هنا، ولكن الحركة الإنتقالية قد تحد من الoverflow. +
    +
    +
    +
    +

    + +

    +
    +
    + هذا هو محتوى عنصر المطوية الثالث. سيكون المحتوى مخفيًا بشكل إفتراضي حتى يقوم Bootstrap بإضافة الكلاسات اللازمة لكل عنصر في المطوية. هذه الكلاسات تتحكم بالمظهر العام ووتتحكم أيضا بإظهار وإخفاء أقسام المطوية عبر حركات CSS الإنتقالية. يمكنك تعديل أي من هذه عبر كلاسات CSS خاصة بك، او عبر تغيير القيم الإفتراضية المقدمة من Bootstrap. من الجدير بالذكر أنه يمكن وضع أي كود HTML هنا، ولكن الحركة الإنتقالية قد تحد من الoverflow. +
    +
    +
    +
    + `} /> + +
    +
    +
    +

    الإنذارات

    + دليل الإستخدام +
    + +
    + ` + + `)} /> + + +

    أحسنت!

    +

    لقد نجحت في قراءة رسالة التنبيه المهمة هذه. سيتم تشغيل نص المثال هذا لفترة أطول قليلاً حتى تتمكن من رؤية كيفية عمل التباعد داخل التنبيه مع هذا النوع من المحتوى.

    +
    +

    كلما احتجت إلى ذلك ، تأكد من استخدام أدوات الهامش للحفاظ على الأشياء لطيفة ومرتبة.

    +
    + `} /> + +
    +
    +
    +

    الشارة

    + دليل الإستخدام +
    + +
    + مثال على عنوان جديد

    +

    مثال على عنوان جديد

    +

    مثال على عنوان جديد

    +

    مثال على عنوان جديد

    +

    مثال على عنوان جديد

    +

    مثال على عنوان جديد

    +

    مثال على عنوان جديد

    +

    مثال على عنوان جديد

    + `} /> + + ` + ${themeColor.title} + `)} /> +
    +
    + +
    +
    +

    الأزرار

    + دليل الإستخدام +
    + +
    + ` + + `), + ``]} /> + + ` + + `)} /> + + زر صغير + + + `} /> +
    +
    + +
    +
    +

    البطاقة

    + دليل الإستخدام +
    + +
    + +
    +
    + +
    +
    عنوان البطاقة
    +

    بعض الأمثلة السريعة للنصوص للبناء على عنوان البطاقة وتشكيل الجزء الأكبر من محتوى البطاقة.

    + اذهب لمكان ما +
    +
    +
    +
    +
    +
    + متميز +
    +
    +
    عنوان البطاقة
    +

    بعض الأمثلة السريعة للنصوص للبناء على عنوان البطاقة وتشكيل الجزء الأكبر من محتوى البطاقة.

    + اذهب لمكان ما +
    + +
    +
    +
    +
    +
    +
    عنوان البطاقة
    +

    بعض الأمثلة السريعة للنصوص للبناء على عنوان البطاقة وتشكيل الجزء الأكبر من محتوى البطاقة.

    +
    +
      +
    • عنصر
    • +
    • عنصر آخر
    • +
    • عنصر ثالث
    • +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    عنوان البطاقة
    +

    هذه بطاقة أعرض مع نص داعم تحتها كمقدمة طبيعية لمحتوى إضافي. هذا المحتوى أطول قليلاً.

    +

    آخر تحديث منذ 3 دقائق

    +
    +
    +
    +
    +
    +
    + `} /> + +
    + + +
    +
    +

    مجموعة العناصر

    + دليل الإستخدام +
    + +
    + +
  • عنصر معطل
  • +
  • عنصر ثاني
  • +
  • عنصر ثالث
  • +
  • عنصر رابع
  • +
  • وعنصر خامس أيضًا
  • + + `} /> + + +
  • عنصر
  • +
  • عنصر ثاني
  • +
  • عنصر ثالث
  • +
  • عنصر رابع
  • +
  • وعنصر خامس أيضًا
  • + + `} /> + + + عنصر مجموعة قائمة default بسيط`, + ...getData('theme-colors').map((themeColor) => ` + عنصر مجموعة قائمة ${themeColor.name} بسيط + `), + `
    + `]} /> + +
    + + + + +
    +
    +

    الصناديق المنبثقة

    + دليل الإستخدام +
    + +
    + + انقر لعرض/إخفاء الصندوق المنبثق + + `} /> + + + انبثاق إلى الأعلى + + + + + `} /> +
    +
    +
    +
    +

    شريط التقدم

    + دليل الإستخدام +
    + +
    + +
    0%
    +
    +
    +
    25%
    +
    +
    +
    50%
    +
    +
    +
    75%
    +
    +
    +
    100%
    +
    + `} /> + + +
    +
    +
    +
    +
    +
    + + `} /> + +
    +
    +
    +

    المخطوطة

    + دليل الإستخدام +
    + +
    +
    + +
    +

    @fat

    +

    محتوى لتوضيح كيف تعمل المخطوطة. ببساطة، المخطوطة عبارة عن منشور طويل يحتوي على عدة أقسام، ولديه شريط تنقل يسهل الوصول إلى هذه الأقسام الفرعية.

    +

    @mdo

    +

    بصرف النظر عن تحسيننا جدوى المكيّفات أو عدم تحسينها، فإن الطلب على الطاقة سيزداد. وطبقاً لما جاء في مقالة معهد ماساشوستس للتكنولوجيا، السالف ذكره، ثمَّة أمر يجب عدم إغفاله، وهو كيف أن هذا الطلب سيضغط على نظم توفير الطاقة الحالية. إذ لا بد من إعادة تأهيل كل شبكات الكهرباء، وتوسيعها لتلبية طلب الطاقة في زمن الذروة، خلال موجات الحرارة المتزايدة. فحين يكون الحر شديداً يجنح الناس إلى البقاء في الداخل، وإلى زيادة تشغيل المكيّفات، سعياً إلى جو لطيف وهم يستخدمون أدوات وأجهزة مختلفة أخرى.

    +

    واحد

    +

    وكل هذه الأمور المتزامنة من تشغيل الأجهزة، يزيد الضغط على شبكات الطاقة، كما أسلفنا. لكن مجرد زيادة سعة الشبكة ليس كافياً. إذ لا بد من تطوير الشبكات الذكية التي تستخدم الجسّاسات، ونظم المراقبة، والبرامج الإلكترونية، لتحديد متى يكون الشاغلون في المبنى، ومتى يكون ثمَّة حاجة إلى الطاقة، ومتى تكون الحرارة منخفضة، وبذلك يخرج الناس، فلا يستخدمون كثيراً من الكهرباء.

    +

    اثنان

    +

    مع الأسف، كل هذه الحلول المبتكرة مكلِّفة، وهذا ما يجعلها عديمة الجدوى في نظر بعض الشركات الخاصة والمواطن المتقشّف. إن بعض الأفراد الواعين بيئياً يبذلون قصارى جهدهم في تقليص استهلاكهم من الطاقة، ويعون جيداً أهمية أجهزة التكييف المجدية والأرفق بالبيئة. ولكن جهات كثيرة لن تتحرّك لمجرد حافز سلامة المناخ ووقف هدر الطاقة، ما دامت لا تحركها حوافز قانونية. وعلى الحكومات أن تُقدِم عند الاهتمام بالتغيّر المناخي، على وضع التشريعات المناسبة. فبالنظم والحوافز والدعم، يمكن دفع الشركات إلى اعتماد الحلول الأجدى في مكاتبها.

    +

    ثلاثة

    +

    وكما يتبيّن لنا، من عدد الحلول الملطِّفة للمشكلة، ومن تنوّعها، وهي الحلول التي أسلفنا الحديث عنها، فإن التكنولوجيا التي نحتاج إليها من أجل معالجة هذه التحديات، هي في مدى قدرتنا، لكنها ربما تتطلّب بعض التحسين، ودعماً استثمارياً أكبر!

    +

    ولا مانع من إضافة محتوى آخر ليس تحت أي قسم معين.

    +
    +
    +
    +
    +
    +
    +

    الدوائر المتحركة

    + دليل الإستخدام +
    + +
    + ` +
    + جار التحميل... +
    + `)} /> + + ` +
    + جار التحميل... +
    + `)} /> +
    +
    +
    +
    +

    الإشعارات

    + دليل الإستخدام +
    + +
    + +
    + + Bootstrap + قبل 11 دقيقة + +
    +
    + مرحبًا بالعالم! هذه رسالة إشعار. +
    +
    + `} /> + +
    +
    +
    +

    التلميحات

    + دليل الإستخدام +
    + +
    + تلميح يظهر في الأعلى + + + + + `} /> +
    +
    +
    + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.css new file mode 100644 index 00000000..5721a028 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.css @@ -0,0 +1,163 @@ +body { + scroll-behavior: smooth; +} + +/** + * Bootstrap "Journal code" icon + * @link https://icons.getbootstrap.com/icons/journal-code/ + */ +.bd-heading a::before { + display: inline-block; + width: 1em; + height: 1em; + margin-right: .25rem; + content: ""; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23999' viewBox='0 0 16 16'%3E%3Cpath d='M4 1h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2h1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1H2a2 2 0 0 1 2-2z'/%3E%3Cpath d='M2 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2z'/%3E%3Cpath fill-rule='evenodd' d='M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z'/%3E%3C/svg%3E"); + background-size: 1em; +} + +/* stylelint-disable-next-line selector-max-universal */ +.bd-heading + div > * + * { + margin-top: 3rem; +} + +/* Table of contents */ +.bd-aside a { + padding: .1875rem .5rem; + margin-top: .125rem; + margin-left: .3125rem; + color: var(--bs-body-color); +} + +.bd-aside a:hover, +.bd-aside a:focus { + color: var(--bs-body-color); + background-color: rgba(121, 82, 179, .1); +} + +.bd-aside .active { + font-weight: 600; + color: var(--bs-body-color); +} + +.bd-aside .btn { + padding: .25rem .5rem; + font-weight: 600; + color: var(--bs-body-color); +} + +.bd-aside .btn:hover, +.bd-aside .btn:focus { + color: var(--bs-body-color); + background-color: rgba(121, 82, 179, .1); +} + +.bd-aside .btn:focus { + box-shadow: 0 0 0 1px rgba(121, 82, 179, .7); +} + +.bd-aside .btn::before { + width: 1.25em; + line-height: 0; + content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ccc' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); + transition: transform .35s ease; + + /* rtl:raw: + transform: rotate(180deg) translateX(-2px); + */ + transform-origin: .5em 50%; +} + +.bd-aside .btn[aria-expanded="true"]::before { + transform: rotate(90deg)/* rtl:ignore */; +} + + +/* Examples */ +.scrollspy-example { + height: 200px; +} + +[id="modal"] .bd-example .btn, +[id="buttons"] .bd-example .btn, +[id="tooltips"] .bd-example .btn, +[id="popovers"] .bd-example .btn, +[id="dropdowns"] .bd-example .btn-group, +[id="dropdowns"] .bd-example .dropdown, +[id="dropdowns"] .bd-example .dropup, +[id="dropdowns"] .bd-example .dropend, +[id="dropdowns"] .bd-example .dropstart { + margin: 0 1rem 1rem 0; +} + +/* Layout */ +@media (min-width: 1200px) { + body { + display: grid; + grid-template-rows: auto; + grid-template-columns: 1fr 4fr 1fr; + gap: 1rem; + } + + .bd-header { + position: fixed; + top: 0; + /* rtl:begin:ignore */ + right: 0; + left: 0; + /* rtl:end:ignore */ + z-index: 1030; + grid-column: 1 / span 3; + } + + .bd-aside, + .bd-cheatsheet { + padding-top: 4rem; + } + + /** + * 1. Too bad only Firefox supports subgrids ATM + */ + .bd-cheatsheet, + .bd-cheatsheet section, + .bd-cheatsheet article { + display: inherit; /* 1 */ + grid-template-rows: auto; + grid-template-columns: 1fr 4fr; + grid-column: 1 / span 2; + gap: inherit; /* 1 */ + } + + .bd-aside { + grid-area: 1 / 3; + scroll-margin-top: 4rem; + } + + .bd-cheatsheet section, + .bd-cheatsheet section > h2 { + top: 2rem; + scroll-margin-top: 2rem; + } + + .bd-cheatsheet section > h2::before { + position: absolute; + /* rtl:begin:ignore */ + top: 0; + right: 0; + bottom: -2rem; + left: 0; + /* rtl:end:ignore */ + z-index: -1; + content: ""; + } + + .bd-cheatsheet article, + .bd-cheatsheet .bd-heading { + top: 8rem; + scroll-margin-top: 8rem; + } + + .bd-cheatsheet .bd-heading { + z-index: 1; + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.js new file mode 100644 index 00000000..e25a89e7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.js @@ -0,0 +1,73 @@ +/* global bootstrap: false */ + +(() => { + 'use strict' + + // Tooltip and popover demos + document.querySelectorAll('.tooltip-demo') + .forEach(tooltip => { + new bootstrap.Tooltip(tooltip, { + selector: '[data-bs-toggle="tooltip"]' + }) + }) + + document.querySelectorAll('[data-bs-toggle="popover"]') + .forEach(popover => { + new bootstrap.Popover(popover) + }) + + document.querySelectorAll('.toast') + .forEach(toastNode => { + const toast = new bootstrap.Toast(toastNode, { + autohide: false + }) + + toast.show() + }) + + // Disable empty links and submit buttons + document.querySelectorAll('[href="#"], [type="submit"]') + .forEach(link => { + link.addEventListener('click', event => { + event.preventDefault() + }) + }) + + function setActiveItem() { + const { hash } = window.location + + if (hash === '') { + return + } + + const link = document.querySelector(`.bd-aside a[href="${hash}"]`) + + if (!link) { + return + } + + const active = document.querySelector('.bd-aside .active') + const parent = link.parentNode.parentNode.previousElementSibling + + link.classList.add('active') + + if (parent.classList.contains('collapsed')) { + parent.click() + } + + if (!active) { + return + } + + const expanded = active.parentNode.parentNode.previousElementSibling + + active.classList.remove('active') + + if (expanded && parent !== expanded) { + expanded.click() + } + } + + setActiveItem() + window.addEventListener('hashchange', setActiveItem) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.rtl.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.rtl.css new file mode 100644 index 00000000..416e39fc --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/cheatsheet.rtl.css @@ -0,0 +1,156 @@ +body { + scroll-behavior: smooth; +} + +/** + * Bootstrap "Journal code" icon + * @link https://icons.getbootstrap.com/icons/journal-code/ + */ +.bd-heading a::before { + display: inline-block; + width: 1em; + height: 1em; + margin-left: .25rem; + content: ""; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23999' viewBox='0 0 16 16'%3E%3Cpath d='M4 1h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2h1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1H2a2 2 0 0 1 2-2z'/%3E%3Cpath d='M2 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2z'/%3E%3Cpath fill-rule='evenodd' d='M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z'/%3E%3C/svg%3E"); + background-size: 1em; +} + +/* stylelint-disable-next-line selector-max-universal */ +.bd-heading + div > * + * { + margin-top: 3rem; +} + +/* Table of contents */ +.bd-aside a { + padding: .1875rem .5rem; + margin-top: .125rem; + margin-right: .3125rem; + color: var(--bs-body-color); +} + +.bd-aside a:hover, +.bd-aside a:focus { + color: var(--bs-body-color); + background-color: rgba(121, 82, 179, .1); +} + +.bd-aside .active { + font-weight: 600; + color: var(--bs-body-color); +} + +.bd-aside .btn { + padding: .25rem .5rem; + font-weight: 600; + color: var(--bs-body-color); +} + +.bd-aside .btn:hover, +.bd-aside .btn:focus { + color: var(--bs-body-color); + background-color: rgba(121, 82, 179, .1); +} + +.bd-aside .btn:focus { + box-shadow: 0 0 0 1px rgba(121, 82, 179, .7); +} + +.bd-aside .btn::before { + width: 1.25em; + line-height: 0; + content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ccc' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); + transition: transform .35s ease; + transform: rotate(180deg) translateX(-2px); + transform-origin: .5em 50%; +} + +.bd-aside .btn[aria-expanded="true"]::before { + transform: rotate(90deg); +} + + +/* Examples */ +.scrollspy-example { + height: 200px; +} + +[id="modal"] .bd-example .btn, +[id="buttons"] .bd-example .btn, +[id="tooltips"] .bd-example .btn, +[id="popovers"] .bd-example .btn, +[id="dropdowns"] .bd-example .btn-group, +[id="dropdowns"] .bd-example .dropdown, +[id="dropdowns"] .bd-example .dropup, +[id="dropdowns"] .bd-example .dropend, +[id="dropdowns"] .bd-example .dropstart { + margin: 0 0 1rem 1rem; +} + +/* Layout */ +@media (min-width: 1200px) { + body { + display: grid; + grid-template-rows: auto; + grid-template-columns: 1fr 4fr 1fr; + gap: 1rem; + } + + .bd-header { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; + grid-column: 1 / span 3; + } + + .bd-aside, + .bd-cheatsheet { + padding-top: 4rem; + } + + /** + * 1. Too bad only Firefox supports subgrids ATM + */ + .bd-cheatsheet, + .bd-cheatsheet section, + .bd-cheatsheet article { + display: inherit; /* 1 */ + grid-template-rows: auto; + grid-template-columns: 1fr 4fr; + grid-column: 1 / span 2; + gap: inherit; /* 1 */ + } + + .bd-aside { + grid-area: 1 / 3; + scroll-margin-top: 4rem; + } + + .bd-cheatsheet section, + .bd-cheatsheet section > h2 { + top: 2rem; + scroll-margin-top: 2rem; + } + + .bd-cheatsheet section > h2::before { + position: absolute; + top: 0; + right: 0; + bottom: -2rem; + left: 0; + z-index: -1; + content: ""; + } + + .bd-cheatsheet article, + .bd-cheatsheet .bd-heading { + top: 8rem; + scroll-margin-top: 8rem; + } + + .bd-cheatsheet .bd-heading { + z-index: 1; + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/index.astro new file mode 100644 index 00000000..ae2752e0 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cheatsheet/index.astro @@ -0,0 +1,1563 @@ +--- +import { getData } from '@libs/data' +import { getVersionedDocsPath } from '@libs/path' +import Example from '@shortcodes/Example.astro' +import Placeholder from '@shortcodes/Placeholder.astro' + +export const title = 'Cheatsheet' +export const extra_css = ['cheatsheet.css'] +export const extra_js = [{ src: 'cheatsheet.js' }] +export const body_class = 'bg-body-tertiary' +--- + +
    +
    +

    + Bootstrap + Cheatsheet +

    + RTL cheatsheet +
    +
    + +
    +
    +

    Contents

    + +
    +
    +

    Typography

    + Documentation +
    + +
    + Display 1

    +

    Display 2

    +

    Display 3

    +

    Display 4

    +

    Display 5

    +

    Display 6

    `} /> + + Heading 1

    +

    Heading 2

    +

    Heading 3

    +

    Heading 4

    +

    Heading 5

    +

    Heading 6

    `} /> + + + This is a lead paragraph. It stands out from regular paragraphs. +

    `} /> + + You can use the mark tag to highlight text.

    +

    This line of text is meant to be treated as deleted text.

    +

    This line of text is meant to be treated as no longer accurate.

    +

    This line of text is meant to be treated as an addition to the document.

    +

    This line of text will render as underlined.

    +

    This line of text is meant to be treated as fine print.

    +

    This line rendered as bold text.

    +

    This line rendered as italicized text.

    `} /> + + `} /> + + +

    A well-known quote, contained in a blockquote element.

    +
    Someone famous in Source Title
    + `} /> + + +
  • This is a list.
  • +
  • It appears completely unstyled.
  • +
  • Structurally, it's still a list.
  • +
  • However, this style only applies to immediate child elements.
  • +
  • Nested lists: +
      +
    • are unaffected by this style
    • +
    • will still show a bullet
    • +
    • and have appropriate left margin
    • +
    +
  • +
  • This may still come in handy in some situations.
  • + `} /> + + +
  • This is a list item.
  • +
  • And another one.
  • +
  • But they're displayed inline.
  • + `} /> +
    +
    + +
    +
    +

    Tables

    + Documentation +
    +
    + + + + # + First + Last + Handle + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + + `} /> + + + + + # + First + Last + Handle + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + + `} /> + + + + + Class + Heading + Heading + + + + + Default + Cell + Cell + `, + ...getData('theme-colors').map((themeColor) => ` + ${themeColor.title} + Cell + Cell + `), + ` + `]} /> + + + + + # + First + Last + Handle + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + + `} /> +
    +
    + +
    +
    +

    Figures

    + Documentation +
    + +
    + + +
    A caption for the above image.
    + `} /> +
    +
    +
    + +
    +

    Forms

    + +
    +
    +

    Overview

    + Documentation +
    + +
    + +
    + + +
    We'll never share your email with anyone else.
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + Radios buttons +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    + + `} /> +
    +
    +
    +
    +

    Disabled forms

    + Documentation +
    + +
    + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    +
    + Disabled radios buttons +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + `} /> +
    +
    +
    +
    +

    Sizing

    + Documentation +
    + +
    + + +
    +
    + +
    +
    + +
    `} /> + + + + +
    + +
    +
    + +
    + `} /> + +
    +
    +
    +

    Input group

    + Documentation +
    + +
    + + @ + +
    +
    + + @example.com +
    + +
    + https://example.com/users/ + +
    +
    + $ + + .00 +
    +
    + With textarea + +
    + `} /> + +
    +
    +
    +

    Floating labels

    + Documentation +
    + +
    + +
    + + +
    +
    + + +
    + + `} /> +
    +
    +
    +
    +

    Validation

    + Documentation +
    + +
    + +
    + + +
    + Looks good! +
    +
    +
    + + +
    + Looks good! +
    +
    +
    + +
    + @ + +
    + Please choose a username. +
    +
    +
    +
    + + +
    + Please provide a valid city. +
    +
    +
    + + +
    + Please select a valid state. +
    +
    +
    + + +
    + Please provide a valid zip. +
    +
    +
    +
    + + +
    + You must agree before submitting. +
    +
    +
    +
    + +
    + + `} /> +
    +
    +
    + +
    +

    Components

    + +
    +
    +

    Accordion

    + Documentation +
    + +
    + +
    +

    + +

    +
    +
    + This is the first item's accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    +

    + +

    +
    +
    + This is the second item's accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    +

    + +

    +
    +
    + This is the third item's accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    + `} /> + +
    +
    +
    +

    Alerts

    + Documentation +
    + +
    + ` + + `)} /> + + +

    Well done!

    +

    Aww yeah, you successfully read this important alert message. This example text is going to run a bit longer so that you can see how spacing within an alert works with this kind of content.

    +
    +

    Whenever you need to, be sure to use margin utilities to keep things nice and tidy.

    +
    + `} /> + +
    +
    +
    +

    Badge

    + Documentation +
    + +
    + Example heading New

    +

    Example heading New

    +

    Example heading New

    +

    Example heading New

    +

    Example heading New

    +

    Example heading New

    +

    Example heading New

    +

    Example heading New

    + `} /> + + ` + ${themeColor.title} + `)} /> +
    +
    + +
    +
    +

    Buttons

    + Documentation +
    +
    + ` + + `), + ``]} /> + + ` + + `)} /> + + Small button + + + `} /> +
    +
    +
    +
    +

    Button group

    + Documentation +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    + +
    +
    + `} /> + +
    +
    +
    +

    Card

    + Documentation +
    + +
    + +
    +
    + +
    +
    Card title
    +

    Some quick example text to build on the card title and make up the bulk of the card's content.

    + Go somewhere +
    +
    +
    +
    +
    +
    + Featured +
    +
    +
    Card title
    +

    Some quick example text to build on the card title and make up the bulk of the card's content.

    + Go somewhere +
    + +
    +
    +
    +
    +
    +
    Card title
    +

    Some quick example text to build on the card title and make up the bulk of the card's content.

    +
    +
      +
    • An item
    • +
    • A second item
    • +
    • A third item
    • +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Card title
    +

    This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

    +

    Last updated 3 mins ago

    +
    +
    +
    +
    +
    +
    + `} /> + +
    + + + + + + + +
    +
    +

    Popovers

    + Documentation +
    + +
    + Click to toggle popover + `} /> + + + Popover on top + + + + + `} /> +
    +
    +
    +
    +

    Progress

    + Documentation +
    + +
    + +
    0%
    +
    +
    +
    25%
    +
    +
    +
    50%
    +
    +
    +
    75%
    +
    +
    +
    100%
    +
    + `} /> + + +
    +
    +
    +
    +
    +
    + + `} /> + +
    +
    +
    +

    Scrollspy

    + Documentation +
    + +
    +
    + +
    +

    First heading

    +

    This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.

    +

    Second heading

    +

    This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.

    +

    Third heading

    +

    This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.

    +

    Fourth heading

    +

    This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.

    +

    Fifth heading

    +

    This is some placeholder content for the scrollspy page. Note that as you scroll down the page, the appropriate navigation link is highlighted. It's repeated throughout the component example. We keep adding some more example copy here to emphasize the scrolling and highlighting.

    +
    +
    +
    +
    +
    +
    +

    Spinners

    + Documentation +
    + +
    + ` +
    + Loading... +
    + `)} /> + + ` +
    + Loading... +
    + `)} /> +
    +
    +
    +
    +

    Toasts

    + Documentation +
    + +
    + +
    + + Bootstrap + 11 mins ago + +
    +
    + Hello, world! This is a toast message. +
    +
    + `} /> + +
    +
    +
    +

    Tooltips

    + Documentation +
    + +
    + Tooltip on top + + + + + `} /> +
    +
    +
    +
    + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout-rtl/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout-rtl/index.astro new file mode 100644 index 00000000..1b019357 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout-rtl/index.astro @@ -0,0 +1,231 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'مثال إتمام الشراء' +export const direction = 'rtl' +export const extra_css = ['../checkout/checkout.css'] +export const extra_js = [{ src: '../checkout/checkout.js' }] +export const body_class = 'bg-body-tertiary' +--- + +
    +
    +
    + +

    نموذج إتمام الشراء

    +

    فيما يلي مثال على نموذج تم إنشاؤه بالكامل باستخدام عناصر تحكم النموذج في Bootstrap. لكل مجموعة نماذج مطلوبة حالة تحقق يمكن تشغيلها بمحاولة إرسال النموذج دون استكماله.

    +
    + +
    +
    +

    + عربة التسوق + 3 +

    +
      +
    • +
      +
      اسم المنتج
      + وصف مختصر +
      + $12 +
    • +
    • +
      +
      المنتج الثاني
      + وصف مختصر +
      + $8 +
    • +
    • +
      +
      البند الثالث
      + وصف مختصر +
      + $5 +
    • +
    • +
      +
      رمز ترويجي
      + EXAMPLECODE +
      + -$5 +
    • +
    • + مجموع (USD) + $20 +
    • +
    + +
    +
    + + +
    +
    +
    +
    +

    عنوان الفوترة

    +
    +
    +
    + + +
    + يرجى إدخال اسم أول صحيح. +
    +
    + +
    + + +
    + يرجى إدخال اسم عائلة صحيح. +
    +
    + +
    + +
    + @ + +
    + اسم المستخدم الخاص بك مطلوب. +
    +
    +
    + +
    + + +
    + يرجى إدخال عنوان بريد إلكتروني صحيح لتصلكم تحديثات الشحن. +
    +
    + +
    + + +
    + يرجى إدخال عنوان الشحن الخاص بك. +
    +
    + +
    + + +
    + +
    + + +
    + يرجى اختيار بلد صحيح. +
    +
    + +
    + + +
    + يرجى اختيار اسم منطقة صحيح. +
    +
    + +
    + + +
    + الرمز البريدي مطلوب. +
    +
    +
    + +
    + +
    + + +
    + +
    + + +
    + +
    + +

    طريقة الدفع

    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + + الاسم الكامل كما هو معروض على البطاقة +
    + الاسم على البطاقة مطلوب +
    +
    + +
    + + +
    + رقم بطاقة الائتمان مطلوب +
    +
    + +
    + + +
    + تاريخ انتهاء الصلاحية مطلوب +
    +
    + +
    + + +
    + رمز الحماية مطلوب +
    +
    +
    + +
    + + +
    +
    +
    +
    + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.css new file mode 100644 index 00000000..e5ea31c4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.css @@ -0,0 +1,3 @@ +.container { + max-width: 960px; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.js new file mode 100644 index 00000000..30ea0aa6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/checkout.js @@ -0,0 +1,19 @@ +// Example starter JavaScript for disabling form submissions if there are invalid fields +(() => { + 'use strict' + + // Fetch all the forms we want to apply custom Bootstrap validation styles to + const forms = document.querySelectorAll('.needs-validation') + + // Loop over them and prevent submission + Array.from(forms).forEach(form => { + form.addEventListener('submit', event => { + if (!form.checkValidity()) { + event.preventDefault() + event.stopPropagation() + } + + form.classList.add('was-validated') + }, false) + }) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/index.astro new file mode 100644 index 00000000..029bc796 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/checkout/index.astro @@ -0,0 +1,231 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Checkout example' +export const extra_css = ['checkout.css'] +export const extra_js = [{ src: 'checkout.js' }] +export const body_class = 'bg-body-tertiary' +--- + +
    +
    +
    + +

    Checkout form

    +

    Below is an example form built entirely with Bootstrap’s form controls. Each required form group has a validation state that can be triggered by attempting to submit the form without completing it.

    +
    + +
    +
    +

    + Your cart + 3 +

    +
      +
    • +
      +
      Product name
      + Brief description +
      + $12 +
    • +
    • +
      +
      Second product
      + Brief description +
      + $8 +
    • +
    • +
      +
      Third item
      + Brief description +
      + $5 +
    • +
    • +
      +
      Promo code
      + EXAMPLECODE +
      + −$5 +
    • +
    • + Total (USD) + $20 +
    • +
    + +
    +
    + + +
    +
    +
    +
    +

    Billing address

    +
    +
    +
    + + +
    + Valid first name is required. +
    +
    + +
    + + +
    + Valid last name is required. +
    +
    + +
    + +
    + @ + +
    + Your username is required. +
    +
    +
    + +
    + + +
    + Please enter a valid email address for shipping updates. +
    +
    + +
    + + +
    + Please enter your shipping address. +
    +
    + +
    + + +
    + +
    + + +
    + Please select a valid country. +
    +
    + +
    + + +
    + Please provide a valid state. +
    +
    + +
    + + +
    + Zip code required. +
    +
    +
    + +
    + +
    + + +
    + +
    + + +
    + +
    + +

    Payment

    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + + Full name as displayed on card +
    + Name on card is required +
    +
    + +
    + + +
    + Credit card number is required +
    +
    + +
    + + +
    + Expiration date required +
    +
    + +
    + + +
    + Security code required +
    +
    +
    + +
    + + +
    +
    +
    +
    + + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/cover.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/cover.css new file mode 100644 index 00000000..2e7aef8f --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/cover.css @@ -0,0 +1,50 @@ +/* + * Globals + */ + + +/* Custom default button */ +.btn-light, +.btn-light:hover, +.btn-light:focus { + color: #333; + text-shadow: none; /* Prevent inheritance from `body` */ +} + + +/* + * Base structure + */ + +body { + text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5); + box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5); +} + +.cover-container { + max-width: 42em; +} + + +/* + * Header + */ + +.nav-masthead .nav-link { + color: rgba(255, 255, 255, .5); + border-bottom: .25rem solid transparent; +} + +.nav-masthead .nav-link:hover, +.nav-masthead .nav-link:focus { + border-bottom-color: rgba(255, 255, 255, .25); +} + +.nav-masthead .nav-link + .nav-link { + margin-left: 1rem; +} + +.nav-masthead .active { + color: #fff; + border-bottom-color: #fff; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/index.astro new file mode 100644 index 00000000..3af73150 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/cover/index.astro @@ -0,0 +1,31 @@ +--- +export const title = 'Cover Template' +export const extra_css = ['cover.css'] +export const html_class = 'h-100' +export const body_class = 'd-flex h-100 text-center text-bg-dark' +--- + +
    +
    +
    +

    Cover

    + +
    +
    + +
    +

    Cover your page.

    +

    Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.

    +

    + Learn more +

    +
    + + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/dashboard.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/dashboard.js new file mode 100644 index 00000000..bdb3029d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/dashboard.js @@ -0,0 +1,49 @@ +/* globals Chart:false */ + +(() => { + 'use strict' + + // Graphs + const ctx = document.getElementById('myChart') + // eslint-disable-next-line no-unused-vars + const myChart = new Chart(ctx, { + type: 'line', + data: { + labels: [ + 'الأحد', + 'الإثنين', + 'الثلاثاء', + 'الأربعاء', + 'الخميس', + 'الجمعة', + 'السبت' + ], + datasets: [{ + data: [ + 15339, + 21345, + 18483, + 24003, + 23489, + 24092, + 12034 + ], + lineTension: 0, + backgroundColor: 'transparent', + borderColor: '#007bff', + borderWidth: 4, + pointBackgroundColor: '#007bff' + }] + }, + options: { + plugins: { + legend: { + display: false + }, + tooltip: { + boxPadding: 3 + } + } + } + }) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/index.astro new file mode 100644 index 00000000..c5758e95 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard-rtl/index.astro @@ -0,0 +1,330 @@ +--- +export const title = 'قالب لوحة القيادة' +export const direction = 'rtl' +export const extra_css = ['../dashboard/dashboard.rtl.css'] +export const extra_js = [ + { src: 'https://cdn.jsdelivr.net/npm/chart.js@4.3.2/dist/chart.umd.js', integrity: 'sha384-eI7PSr3L1XLISH8JdDII5YN/njoSsxfbrkCTnJrzXt+ENP5MOVBxD+l6sEG4zoLp'}, + { src: 'dashboard.js'} +] +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    +
    +

    لوحة القيادة

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

    عنوان القسم

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #عنوانعنوانعنوانعنوان
    1,001بياناتعشوائيةتثريالجدول
    1,002تثريمبهةتصميمتنسيق
    1,003عشوائيةغنيةقيمةمفيدة
    1,003معلوماتتثريتوضيحيةعشوائية
    1,004الجدولبياناتتنسيققيمة
    1,005قيمةمبهةالجدولتثري
    1,006قيمةتوضيحيةغنيةعشوائية
    1,007تثريمفيدةمعلوماتمبهة
    1,008بياناتعشوائيةتثريالجدول
    1,009تثريمبهةتصميمتنسيق
    1,010عشوائيةغنيةقيمةمفيدة
    1,011معلوماتتثريتوضيحيةعشوائية
    1,012الجدولتثريتنسيققيمة
    1,013قيمةمبهةالجدولتصميم
    1,014قيمةتوضيحيةغنيةعشوائية
    1,015بياناتمفيدةمعلوماتالجدول
    +
    +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.css new file mode 100644 index 00000000..154940c9 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.css @@ -0,0 +1,48 @@ +.bi { + display: inline-block; + width: 1rem; + height: 1rem; +} + +/* + * Sidebar + */ + +@media (min-width: 768px) { + .sidebar .offcanvas-lg { + position: -webkit-sticky; + position: sticky; + top: 48px; + } + .navbar-search { + display: block; + } +} + +.sidebar .nav-link { + font-size: .875rem; + font-weight: 500; +} + +.sidebar .nav-link.active { + color: #2470dc; +} + +.sidebar-heading { + font-size: .75rem; +} + +/* + * Navbar + */ + +.navbar-brand { + padding-top: .75rem; + padding-bottom: .75rem; + background-color: rgba(0, 0, 0, .25); + box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25); +} + +.navbar .form-control { + padding: .75rem 1rem; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.js new file mode 100644 index 00000000..a60b3935 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.js @@ -0,0 +1,49 @@ +/* globals Chart:false */ + +(() => { + 'use strict' + + // Graphs + const ctx = document.getElementById('myChart') + // eslint-disable-next-line no-unused-vars + const myChart = new Chart(ctx, { + type: 'line', + data: { + labels: [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday' + ], + datasets: [{ + data: [ + 15339, + 21345, + 18483, + 24003, + 23489, + 24092, + 12034 + ], + lineTension: 0, + backgroundColor: 'transparent', + borderColor: '#007bff', + borderWidth: 4, + pointBackgroundColor: '#007bff' + }] + }, + options: { + plugins: { + legend: { + display: false + }, + tooltip: { + boxPadding: 3 + } + } + } + }) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.rtl.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.rtl.css new file mode 100644 index 00000000..5c8a7e25 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/dashboard.rtl.css @@ -0,0 +1,48 @@ +.bi { + display: inline-block; + width: 1rem; + height: 1rem; +} + +/* + * Sidebar + */ + +@media (min-width: 768px) { + .sidebar .offcanvas-lg { + position: -webkit-sticky; + position: sticky; + top: 48px; + } + .navbar-search { + display: block; + } +} + +.sidebar .nav-link { + font-size: .875rem; + font-weight: 500; +} + +.sidebar .nav-link.active { + color: #2470dc; +} + +.sidebar-heading { + font-size: .75rem; +} + +/* + * Navbar + */ + +.navbar-brand { + padding-top: .75rem; + padding-bottom: .75rem; + background-color: rgba(0, 0, 0, .25); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, .25); +} + +.navbar .form-control { + padding: .75rem 1rem; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/index.astro new file mode 100644 index 00000000..4d33c7fb --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dashboard/index.astro @@ -0,0 +1,329 @@ +--- +export const title = 'Dashboard Template' +export const extra_css = ['dashboard.css'] +export const extra_js = [ + { src: 'https://cdn.jsdelivr.net/npm/chart.js@4.3.2/dist/chart.umd.js', integrity: 'sha384-eI7PSr3L1XLISH8JdDII5YN/njoSsxfbrkCTnJrzXt+ENP5MOVBxD+l6sEG4zoLp'}, + { src: 'dashboard.js'} +] +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    +
    +

    Dashboard

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

    Section title

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #HeaderHeaderHeaderHeader
    1,001randomdataplaceholdertext
    1,002placeholderirrelevantvisuallayout
    1,003datarichdashboardtabular
    1,003informationplaceholderillustrativedata
    1,004textrandomlayoutdashboard
    1,005dashboardirrelevanttextplaceholder
    1,006dashboardillustrativerichdata
    1,007placeholdertabularinformationirrelevant
    1,008randomdataplaceholdertext
    1,009placeholderirrelevantvisuallayout
    1,010datarichdashboardtabular
    1,011informationplaceholderillustrativedata
    1,012textplaceholderlayoutdashboard
    1,013dashboardirrelevanttextvisual
    1,014dashboardillustrativerichdata
    1,015randomtabularinformationtext
    +
    +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/dropdowns.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/dropdowns.css new file mode 100644 index 00000000..f633e2cd --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/dropdowns.css @@ -0,0 +1,71 @@ +.dropdown-item-danger { + color: var(--bs-red); +} +.dropdown-item-danger:hover, +.dropdown-item-danger:focus { + color: #fff; + background-color: var(--bs-red); +} +.dropdown-item-danger.active { + background-color: var(--bs-red); +} + +.btn-hover-light { + color: var(--bs-body-color); + background-color: var(--bs-body-bg); +} +.btn-hover-light:hover, +.btn-hover-light:focus { + color: var(--bs-link-hover-color); + background-color: var(--bs-tertiary-bg); +} + +.cal-month, +.cal-days, +.cal-weekdays { + display: grid; + grid-template-columns: repeat(7, 1fr); + align-items: center; +} +.cal-month-name { + grid-column-start: 2; + grid-column-end: 7; + text-align: center; +} +.cal-weekday, +.cal-btn { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: center; + height: 3rem; + padding: 0; +} +.cal-btn:not([disabled]) { + font-weight: 500; + color: var(--bs-emphasis-color); +} +.cal-btn:hover, +.cal-btn:focus { + background-color: var(--bs-secondary-bg); +} +.cal-btn[disabled] { + border: 0; + opacity: .5; +} + +.w-220px { + width: 220px; +} + +.w-280px { + width: 280px; +} + +.w-340px { + width: 340px; +} + +.opacity-10 { + opacity: .1; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/index.astro new file mode 100644 index 00000000..812109e4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/dropdowns/index.astro @@ -0,0 +1,459 @@ +--- +export const title = 'Dropdowns' +export const extra_css = ['dropdowns.css'] +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + +
    + + + +
    + +
    + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/features.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/features.css new file mode 100644 index 00000000..debc2636 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/features.css @@ -0,0 +1,26 @@ +.feature-icon { + width: 4rem; + height: 4rem; + border-radius: .75rem; +} + +.icon-square { + width: 3rem; + height: 3rem; + border-radius: .75rem; +} + +.text-shadow-1 { text-shadow: 0 .125rem .25rem rgba(0, 0, 0, .25); } +.text-shadow-2 { text-shadow: 0 .25rem .5rem rgba(0, 0, 0, .25); } +.text-shadow-3 { text-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .25); } + +.card-cover { + background-repeat: no-repeat; + background-position: center center; + background-size: cover; +} + +.feature-icon-small { + width: 3rem; + height: 3rem; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/index.astro new file mode 100644 index 00000000..7a3a7640 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/index.astro @@ -0,0 +1,337 @@ +--- +export const title = 'Features' +export const extra_css = ['features.css'] +--- + + + + Bootstrap + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Features examples

    + + + +
    + +
    +

    Hanging icons

    +
    +
    +
    + +
    +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

    + + Primary button + +
    +
    +
    +
    + +
    +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

    + + Primary button + +
    +
    +
    +
    + +
    +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

    + + Primary button + +
    +
    +
    +
    + +
    + +
    +

    Custom cards

    + +
    +
    +
    +
    +

    Short title, long jacket

    +
      +
    • + Bootstrap +
    • +
    • + + Earth +
    • +
    • + + 3d +
    • +
    +
    +
    +
    + +
    +
    +
    +

    Much longer title that wraps to multiple lines

    +
      +
    • + Bootstrap +
    • +
    • + + Pakistan +
    • +
    • + + 4d +
    • +
    +
    +
    +
    + +
    +
    +
    +

    Another longer title belongs here

    +
      +
    • + Bootstrap +
    • +
    • + + California +
    • +
    • + + 5d +
    • +
    +
    +
    +
    +
    +
    + +
    + +
    +

    Icon grid

    + +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    +
    + +
    + +
    +

    Features with title

    + +
    +
    +

    Left-aligned title explaining these awesome features

    +

    Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

    + Primary button +
    + +
    +
    +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    + +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    + +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    + +
    +
    + +
    +

    Featured title

    +

    Paragraph of text beneath the heading to explain the heading.

    +
    +
    +
    +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-1.jpg b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..283acd0b4cade8542cb1010aa7b2b28d0f58fd54 GIT binary patch literal 10433 zcmeHtcT^MI*Y1SSdlv)(0;19+v`FtD(m_OuKmh4oIwBw-y(l6HB27VxQlt~4SEcuk z^j<>mT*Tk2e)o_2&t2=gcYW)fNoJn2_cP}_XV1x=oRgdnosR;60QSX(gN=iWi-S*a zv6B!J5)zY8lagKR)XY@0R2MI12rGpC;w{L|#>Orv&d?|7`{5 zbpRPImOMBR3}OZ_$UtB+(0Kzu4}bs+FbD(!es7pqAPn$@((@4j_m}--=(qD<@NWeE zjlloo2v~Sm%h?S^T=f+q`CAFb@#5Lwz>}#Fc{{VM?FsO_A)n-5ev1*G*uE8tM|?=A zKymDC`y~CDbAT`EFNT*xwYR0K_LnKReE}w8F>yd9skfajw}`@+z1&StG*=83-;JtDvh=2V1U@I%^jQr;e&p^ zndH8@-pO1V`bm3(aiq6gvKGic1`{o`6z6;_DV$T<#%21=WboDX;SFw)3Ai?K-}>OK zj$~c{3GIZAkVf{x!aIk^AHRvikf57wTArG_F1naY>3j z??8m(`Nudvb5zJ7Cqzkvw6w6VzxKEp%;32_NNAJ!4;Q@Wkl$0GH0Z)96D9DqHam!mX{pPYBV=he<*7ex` zXavA}gDK7dvswI8^Jaa{@ut{s(&!Dfm>Yw0Pl}spYJT%*PX})$FcK{sj%l{%ZXX{p zazM02ukKa8ceaUqX#AT-bPl*fM>`IxVUq**ExyTw!;I6z>&b4P)+i!xCoeJ9-fxR{YnR=Iz|4*(L1KD;@q1twby_*jor#O_~R7j>P>sF?X92oMiAdj6Ky z|J@zOP$LC7eFdCgE}@m2Kcg4`m9D5M>Ourj{S9+h!#f{nH-$GRCCvQA0KAj?Ub2_3 zG=0fS#Amnub};6#l<}9;i!f8|ButPB*JR{<%1-|jekEQ^;IF#?VCXCl#~jFg3f56m z(KWgfE$(IA_m@OS@=kzWMMCy+wslM5o$X$Ozpn+nI;&m%7ucD42Ogkjz9%7?{<;zn zvlu>kh>REYeZl<;?G0IbsC*8)^j=rX5X6{kOO1pv_KV#yAFzUk&d#(%901o!@c zJLb9c{_nm6pb>e`tw96hzncX*l>fS&|Hbof;ok`S8-f3Z2!Jo9KUXehK7Y@BE}FfV z{9Mj_Fi8I!H2i<%tO_D9)ttSwa4LOm>vz6{uesOEBYymZc+wpSZ*YnQHtsxPY z01&nj`o#md{&W6i{~vs0{67z3FzNr`zW;As)B82ZfPM|y_Dk0lxi{topSpfxtP(BJ z&7K>^KQYk*SH6fj^-0N}1py7`g%Iir^`E$;&F(h0$>&nZ3k-5WzUlDb>KXazAQFH& zE>Pvz{luV*k3!+?_6bEl3t$Vb8NwW$`aO^mR|oa8{XAl z=l}6XoQsjoLJEK{)~7BPsD7pCi|mXEU|}2Mkdaf6Qr1xYXORko0h|Lvi?3RzhtGJ8 zLMEqi4&EeFFK>!5I6+$b4hA2gsc(bZIx8*ppUtw?y;f~*5RnKGi3VJD&jMP=1vCSUu`lM6(l74-$N^jRfYbBqmk#_sr znks?OLiylf{rC4|xOfdTsuf(lUDgHcD z`w!JKE8Fk)dTVo74|jjOH{NKNk6K;Xx3n=A*>Vg1;`24IbZVETd8Qgjhb^YF_Zd&7 zcXJ5ltZ;YgS@sR)fn#|)xGcg~U-i2bkE*76cm+2mVU86#eCDebkKt2QtkczP#NvF2 zijtr#{2Xa|@2jq50%X3z{QJ@*jfeCbyW_kM4^ku6wJCJdUlnx@eY?KCI;Xa=ufUq< z3hR}3nB3ty?v+qkadh$FnLl34LDP3HaAqYGuC5{nBzCOKiN2LNw?VSUn7MDcnbhQe zTv^XrN+$Bi4V(FBmGOpiLxpUf|HRTxcskHX>>$jemKcG$a}QfUhj4WkMK1F!xmUOf zmA$eY;eGE^k4wS696C_p&GBKIEi`Q-;PVwZJORs!{5j-ZLZw$8zMWsx(oguhATa(? z6ElH(%gdE(VN@2pX{=5k9n1SJx}W8_B*FJ!cZj@4EIZ4l%9!=sshm z>vYjayk$RfxxYxMuN`5S=ynR_zmc5w>{O)bs4H6H>%EgN!&Sv;%GqBJ*}Cs7o&$>m z9lM3Y?AufPGw~*#`+GhzQ%PkM-<@~P1UekG8NR1$b3EKC$*~zf{rp~zLpJ~Y;88I{ z>+!BckYk&M^&>s|aIOe{@^b$4qE2&>J<1<*uJKPgyB)f3^j8Ts!*a&eIP=<3f-SuS zZVUy3cv{f;!Q*rW=`-3}b(0n+;yKf}1R`6JLvC8@f_q}I<%3H3R(*65x9VQscUbwh zxxKL(yX@!cWTM-FTGNYYDHmjFEX_8Ji-sAoEHx1anJ|2RaSn(d?k`)l+3K>_7e;Nv z2e{UDj!=-=6pO;B;ahr9`jKZS(u=rOYtf^}t?9yj##Z4E@4?b+ODyIff~z7pvutyb z_2)of5{!f-=YY7dDP7mf%vJm0=9o3Jlermgnc zjZ!46usy>xzfGAVfpt2E`V%T6hk$*bUeFUX4_%)XjrgaOzgemf}tA zMn|GV1cFA)vsVw^2fGOV=tnjfiss#1RWxZ+yb(O`#3*lKI)Wi8q;aEGg^xz?#~VJ8 z?#|^;W1_5^N0W^V<#R1lGo|Qk>aG{Uyo*sq&`gtc-O#BU181=HrS@LduZj!(9^V~% zS9$Yu9*suU*Qw>^co@Yjs(pml87d=bA;jm!Av>KB7Lgv=Pf}Eb~y@lc3)6TsljD?4Sl!R!mi&A)`r1zIaT=nXcvz zSZ^ifh(JvgC7ylnb7#=;&ZSn``gHQ_BKjnSb*BzU-Cg`(PPL0t(ah??Xm|3@UX)xP z)Y-9zFm4_@tnBWe1Nj^mxmASpBC&$NU<^!5Fg6y}#q;DMiIRaa$**BSrII&*i-J#@o@yp$h>{$eB~vZ=-|qR6zkkmv zulH(adVBQAU0IfO!_xlFeJ)~yfbadckB~W!N&38^I9a}#?iL+LNGC2C-LFSIw(4;~ zJYOohSeRSZ+=2_Hx~jH^**w`5*bs~ z2Qju1Yy7m}k^uc!vdz2|T{NT8So;T|g6Piheg?b;nz-vEV+`(}L2*z*8j0O6BLT;F zU0%ip<@xXI;fG%~cFC%4lG`a-7JfABhU?*()iYh+Oy2}!kKA1G1cuBzSSIm=Zx=x1YfjtayJ|(yb7p?AU1rG39yx5Z6?07 zNDP9=QJ0o6Fn&1lNmaidWD{=VOsJqI8v0^Qc_`^Qn>?1^yhUw1ydtuZuKXMj<)V4U zV%o6eV*_f=uKQ%uGZSny)bYMYX|B<8XJ$Kd&ev(Ll@;J@8|e-<8VG>bj`N?sYesqF zedsoBPVa#$Ka5eo4}f^h>_U9E`Mk8FA%nLc{Z7fv zvqBzmR3>dg=xpPV-gK@BLza1*!=WFtYVS+aH~M!UqA{pUZnpbr%#-J+Iij6-KXto` zn%yCYA(5975GGs;=RIq#J=W6t+&9&0g%(sUH(+PpXKlYx@8#OJK=9UZWw~{R@gxgZ z6Vt>k_E>6GO*{J8wG9xnsi7`g_<C|&6NJcsEFn&#m!&!A@^+ATzp z!wH2QZGkuq^-G=28I0x=hY_BnuJN}ks}ptWeWQ57{jS8naT~<6{{D6W8bpu$I5>6Z z3(3$S1$Q)5e%8amx9H2lH$(x82ntJE!z^|PFJNko*+wAbbDwiw=01)8NjN~t4h6_D zEd(ELUYiLIFO8+4Lt|R!+he&^^)3s5Dct$4X0neZ@4YpubTk%Z0_vDyur?5)q00Q4 zzs|dwO;hXVOs&cy%2^Q{;`5}B=>{ulhVE(4>pPCgA$IS4Gg}yHs*g!MmMaPm&vm7D zMGowgMbBy-cD69h^9eD2f`91BmUr?LFuzabDSl-PRj`yKyC42m-v=998~p5twL_EPV$}8_F;K;_VM9g8K0b$> z=XO~rTZKPhI!zLuFWM!tHVjrixgAk1mKKIlwt8KchtE!nHhBlz9{X5H1EWzM`@PWk zSy$#2N~>B?Tzb9ntoRyAnlWzf1Dw!c4E9vk{sKRS1~h@*0YmyNHfmN$?lvtT5b;?4 zQ9G)4jUb8$yag93_vNW~+}Lw__CBv?ag%GdJx)Vm**reY<=qXnUJ`lAw5NrhrqF5D z$;@U$0`+a80-W-|C!z;0R#j$W;6Lu{DhN^gXGeT)X#c7m%0!I$E$Iu9sBy+%DKn3u zcR)=5%)2aE8Ss`fH4U|uv*KnQ?!N`Ms1GqoNUY$SG8;Mx~@qd z+Umj2fu(7aruJ1fgF`w#a1jjxE%f-r0GHiVVsEd+@pCZF_~#N2&bYG#uMs2ql6BGA|QC+=87dI_Lh#`p0qK6?)Y ztg6v;nRBf&7#i^9$cok<5M}Q6HFiEy?pxHd_wz9ea7AmZQ!;T_zXhzZBxhPzRB7)R z8+{Dlb&nHDN`kwK;*$!h-!6~0OhF6cvmjrNT8B}X22zs}%Qgm3P&FwXw;hhO^6=pP z=tge7uonc22|T^uQilqC`EXqi+w^+NX`sBRqcd2YJXI7|28^ffFxTlD&xZi{on{E@ z)cL@uN1h_iO4QJ1^TeQ_1j?pa<&JW}=l0^9!L?+4v+6j|hg^dU5d9f z?^&;yR-Vf^sXnbMF5L;toSiw1i`@^{!=QF$-DDg1QU99i2BHjYM|qRNsYG06(nWoL zgL1QGe~pw0|F!b2fo)cSNZZh`6s$CaIxz~ZAw#^$y8*Yu1;%OLm5ocPG}R_$6b{K@ zmLe7#+Ef)ecqXrqx{>MSA>v0!Eqy*!M28ky58GO~G(>kNhqk`ZMv&pHD+@_+-eq!R zKIMsK*q+4~fn00S_ni|}a33?_1}n89(W%4Zfksp7t={`TFKmd9$X02QOL>vdsvop^51+rEV6aqa4O|lMVlP?g-~VXB{5Gm zpn@RXujA=invCv>8n934WQXD%LToztm0;Sw~}jHfUq?KA0y9t z-E_KxYVb&A2ZZAwDu*2tYXV@>VqEVcWk&?l+4GdKlTh7iiEs!3u+x!uWiihIW1W!! zYi>wwdPYRbd`3_cv>`Aw3Q>2scxI@mZA-u`BMX;r z!Anb5h_4HA2m5ohRn|;eg;;%mh#0OVstMZSxe=00fTt?;kZ917vg-{yU8>mG@NVAv z^~Iu(=Kx&d=-m%DM&G^> z!?Nrg_BGqY+@8n@!+c1;ZP>pYO`E{{*?-x;ARJLrvW~tBCpyVC8WkYUOL6%u~Q$1NbL4{DGJ&hiXOU|*vTMv!F zTV}>=)1Sb&3$;IKO40h-){(t5h7a9YPW1BT?AJ=5Z# z5ZnB)BAZ$l2A@+`~%9+)20SpWO>9&w)U8_PRldK>KX5;tB zm#rxcAy;m^4Ubn2`%d;O6>z+JnyO(VZ?>dp;>PM<`NT|@j_cG`wh%N}5^-Zx%~wJ53P@hi& z#XgxPF27X1IRw?UDZa5mbDzy=mdAe}+KHC(ImyM>GrVU_Wbs;N%CM+P&QjFa zwiv72Hc&mGW2zoCJP_ zolnYM(5t~ps!mUt023-h5+n*C3ELt+o9)|yq?E_JsXH-mUN2PaD?$_t+xmAmJ5hQm z`dwq{6KkcfdEeA#VVJ~V4L&%>u2+QJ1Tlx`pRo3W4`+o#D&CM z@;HP@>RM7iP=Ki)oL*&`^zF5ECL7pRmhY40BSDoHTULmpg5zg7{5}fzkVS`7{(GXK zkJHDl$o3V(MC$hq^U|&5ZMm8k)Cg~=EgwiJjK+{?LZ>pVG`C^AUJFKEv^9an94u zxf!(-5Hkbe?&4zyh6v>rI=bg1FL5y$D+Tma$vP$v)U1Nl#h$$h^TgSp4;@ZFyGDg# ztc;M@^-sQ-%`%hy{2v>D0mAy{pKKt2jFd?o1DZm9jYmpawZ+4{t#l;!OHQ4CD@@ov+rdn|QVD3l#0tvS*l@dyl+Nh33%}JXVu2eiZR2 abJ%1@Fv6WCPBW&URN4t~ntaiX;r|5+>TPWR literal 0 HcmV?d00001 diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-2.jpg b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/features/unsplash-photo-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..81eae64d8ef72b92bd67d3095ae35584aca93790 GIT binary patch literal 113000 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 literal 0 HcmV?d00001 diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/footers/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/footers/index.astro new file mode 100644 index 00000000..9aaaa9f6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/footers/index.astro @@ -0,0 +1,179 @@ +--- +export const title = 'Footers' +--- + + + + Bootstrap + + + + + + + + + + + + +
    + +
    +
    +
    + + + + © {new Date().getFullYear()} Company, Inc +
    + + +
    +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + + +
    + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/grid.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/grid.css new file mode 100644 index 00000000..cbc7c311 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/grid.css @@ -0,0 +1,13 @@ +.themed-grid-col { + padding-top: .75rem; + padding-bottom: .75rem; + background-color: rgba(112.520718, 44.062154, 249.437846, .15); + border: 1px solid rgba(112.520718, 44.062154, 249.437846, .3); +} + +.themed-container { + padding: .75rem; + margin-bottom: 1.5rem; + background-color: rgba(112.520718, 44.062154, 249.437846, .15); + border: 1px solid rgba(112.520718, 44.062154, 249.437846, .3); +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/index.astro new file mode 100644 index 00000000..2c01d8de --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/grid/index.astro @@ -0,0 +1,185 @@ +--- +export const title = 'Grid Template' +export const extra_css = ['grid.css'] +export const body_class = 'py-4' +--- + +
    +
    + +

    Bootstrap grid examples

    +

    Basic grid layouts to get you familiar with building within the Bootstrap grid system.

    +

    In these examples the .themed-grid-col class is added to the columns to add some theming. This is not a class that is available in Bootstrap by default.

    + +

    Five grid tiers

    +

    There are five tiers to the Bootstrap grid system, one for each range of devices we support. Each tier starts at a minimum viewport size and automatically applies to the larger devices unless overridden.

    + +
    +
    .col-4
    +
    .col-4
    +
    .col-4
    +
    + +
    +
    .col-sm-4
    +
    .col-sm-4
    +
    .col-sm-4
    +
    + +
    +
    .col-md-4
    +
    .col-md-4
    +
    .col-md-4
    +
    + +
    +
    .col-lg-4
    +
    .col-lg-4
    +
    .col-lg-4
    +
    + +
    +
    .col-xl-4
    +
    .col-xl-4
    +
    .col-xl-4
    +
    + +
    +
    .col-xxl-4
    +
    .col-xxl-4
    +
    .col-xxl-4
    +
    + +

    Three equal columns

    +

    Get three equal-width columns starting at desktops and scaling to large desktops. On mobile devices, tablets and below, the columns will automatically stack.

    +
    +
    .col-md-4
    +
    .col-md-4
    +
    .col-md-4
    +
    + +

    Three equal columns alternative

    +

    By using the .row-cols-* classes, you can easily create a grid with equal columns.

    +
    +
    .col child of .row-cols-md-3
    +
    .col child of .row-cols-md-3
    +
    .col child of .row-cols-md-3
    +
    + +

    Three unequal columns

    +

    Get three columns starting at desktops and scaling to large desktops of various widths. Remember, grid columns should add up to twelve for a single horizontal block. More than that, and columns start stacking no matter the viewport.

    +
    +
    .col-md-3
    +
    .col-md-6
    +
    .col-md-3
    +
    + +

    Two columns

    +

    Get two columns starting at desktops and scaling to large desktops.

    +
    +
    .col-md-8
    +
    .col-md-4
    +
    + +

    Full width, single column

    +

    + No grid classes are necessary for full-width elements. +

    + +
    + +

    Two columns with two nested columns

    +

    Per the documentation, nesting is easy—just put a row of columns within an existing column. This gives you two columns starting at desktops and scaling to large desktops, with another two (equal widths) within the larger column.

    +

    At mobile device sizes, tablets and down, these columns and their nested columns will stack.

    +
    +
    +
    + .col-md-8 +
    +
    +
    .col-md-6
    +
    .col-md-6
    +
    +
    +
    .col-md-4
    +
    + +
    + +

    Mixed: mobile and desktop

    +

    The Bootstrap v5 grid system has six tiers of classes: xs (extra small, this class infix is not used), sm (small), md (medium), lg (large), xl (x-large), and xxl (xx-large). You can use nearly any combination of these classes to create more dynamic and flexible layouts.

    +

    Each tier of classes scales up, meaning if you plan on setting the same widths for md, lg, xl and xxl, you only need to specify md.

    +
    +
    .col-md-8
    +
    .col-6 .col-md-4
    +
    +
    +
    .col-6 .col-md-4
    +
    .col-6 .col-md-4
    +
    .col-6 .col-md-4
    +
    +
    +
    .col-6
    +
    .col-6
    +
    + +
    + +

    Mixed: mobile, tablet, and desktop

    +
    +
    .col-sm-6 .col-lg-8
    +
    .col-6 .col-lg-4
    +
    +
    +
    .col-6 .col-sm-4
    +
    .col-6 .col-sm-4
    +
    .col-6 .col-sm-4
    +
    + +
    + +

    Gutters

    +

    With .gx-* classes, the horizontal gutters can be adjusted.

    +
    +
    .col with .gx-4 gutters
    +
    .col with .gx-4 gutters
    +
    .col with .gx-4 gutters
    +
    .col with .gx-4 gutters
    +
    .col with .gx-4 gutters
    +
    .col with .gx-4 gutters
    +
    +

    Use the .gy-* classes to control the vertical gutters.

    +
    +
    .col with .gy-4 gutters
    +
    .col with .gy-4 gutters
    +
    .col with .gy-4 gutters
    +
    .col with .gy-4 gutters
    +
    .col with .gy-4 gutters
    +
    .col with .gy-4 gutters
    +
    +

    With .g-* classes, the gutters in both directions can be adjusted.

    +
    +
    .col with .g-3 gutters
    +
    .col with .g-3 gutters
    +
    .col with .g-3 gutters
    +
    .col with .g-3 gutters
    +
    .col with .g-3 gutters
    +
    .col with .g-3 gutters
    +
    +
    + +
    +
    + +

    Containers

    +

    Additional classes added in Bootstrap v4.4 allow containers that are 100% wide until a particular breakpoint. v5 adds a new xxl breakpoint.

    +
    + +
    .container
    +
    .container-sm
    +
    .container-md
    +
    .container-lg
    +
    .container-xl
    +
    .container-xxl
    +
    .container-fluid
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/headers.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/headers.css new file mode 100644 index 00000000..f887573f --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/headers.css @@ -0,0 +1,15 @@ +.form-control-dark { + border-color: var(--bs-gray); +} +.form-control-dark:focus { + border-color: #fff; + box-shadow: 0 0 0 .25rem rgba(255, 255, 255, .25); +} + +.text-small { + font-size: 85%; +} + +.dropdown-toggle:not(:focus) { + outline: 0; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/index.astro new file mode 100644 index 00000000..a233ae90 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/headers/index.astro @@ -0,0 +1,294 @@ +--- +export const title = 'Headers' +export const extra_css = ['headers.css'] +--- + + + + Bootstrap + + + + + + + + + + + + + + + + + + + + + +
    +

    Headers examples

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









    +
    +
    +









    +
    +
    +
    + +
    + + +
    + +
    + +
    + +
    + +
    +
    + + +
    + + +
    +
    +
    +
    + +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/bootstrap-docs.png b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/bootstrap-docs.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e9b9864a2785f918865cf7704a815893ff3cce GIT binary patch literal 369528 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 A*OoM? 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

    tZZ~$9{!_}(NAnmouTQ)`1jo$Z;&)ZGG4~} zju)3skdVH^3n->{yzhCRaMvL39P7~t;p&%p5ZQwEJ5GH3YYiNNk57Lwh+zyD}+ZEbUC$S~=nA8s8lYVmcv z((z92$UCGNTIA4?K0moFq$sX92XBZQVn4(U9d{yXKz2xOsHov0bmFBN-e1CY>Ea~t zj&{5uO_%YCiiT>-!CJB|$kTwmcec$@h;~+9zjC=1euIMEY^%iK1jP6vGG02U_2m@t z5_kif`;kx>ymsmHv$t|hIbI`<$W5mZx+J2lqjl10nKd{aG{DKYbiCy&qCqbxLrN7= z>u;`uZ~;Z-4vhpv&r85fqdD%N-Hj#h?g{L!uC7AT@aS0{l*_Abr0^6keyEQ3w7?t2 zZnQ~G$nnmUGz8!cSCi2*T26MZF%jiZ#H({%*707TCR;&I>i+1T+qmKG(##p}WF3z) zyiki!ZdE<152I-z-Euk8+W1Vj!ZWdfyIWhHu-Z}bdMB+ar#7J6UWDT%^p2`(5E+d` z1{H@4XS~PN%2dkQ?-3P!$7^_)F-Yhp1MmWCbNO6SxL=hupyEq6L^ZFI!CJBmxaC5s z0xGPhKy5jSmAKo!@-;P>#C&&c2e|t$tE;zwyRcLku$zN4BbSzTmktZ+PNstpyk||Y zbQIZZExavcDC3QW4Mfe^x%)x5j8{pKciaSubE!GDwiP(G0KEW~Kxw~J$9qANL(H$4 zJL6r1xZB-sV_B|f9z|(Ex7>-h*H=oqHO$uPN_)G@6s^MK^@>HESQ)Bn;PI}<7%P`O zx6GyiZ>XM31vSA0ihjF`k0Rw{c>8o2g8jb1Yt->^93!u*gtT=!1YU$NzHrI`dCU2o zUyd7;+m%+e(JwC78Kl4+=t?%O-hs->s;y=KJ>_^U7EAVGN$sB#u}m^M zo0-V2c_!`5^_wE@rXJL9E?;S+7i@G8sebdqb7H4u3n0C7h{53A+w zKKL{xdZELfx}>KHZ6^g}?okIEBrjTC#O){l^N`Zr+=IRQ&;;`E)~(Bz0lbHY&w#qZ zUndE*C^d*;5#VibTIY3U1m36KKv)`$I-I|Acvx>J@J?L0rp8_V-3PPxY6$3y=#E4U z620dc@093}Ws36e@P5=l)`Q3~cOCC!Lx+#avYFR;y+UQV1KqLye8(ua1(IOmgtzn)q0V)xei}{B& z2I_d>F&?~X-P-KE8q_Bu+>JKL2``{Hm!%rY%9U%jo>ihhq}PP|ON+>OqbvVp9dCcK zyXqr9o`3J+cor@blS=P z{!tt#jh>gl8%uq4?XOh-fUDJZAHM|0dzrBN>~J*^lS&e5l@>CAg1B32oGH}+m6SBV z$s)ciG;?ii)DZq%ZJtKx(XNmLUa83wD9+0o0&ZAbp@T8et0B}7Rf6~SqB362%u=g` z(>W2DN8>V2?v`5{Wmk{9Z*jL8bacCzHuTc% z%uizv?|qYq$H4RUQjXu%%JHSY{3030dWI)|+}(Zr_~rA}TbFM_CD{QuUgUWUw;u<6 znbg#^g@9L}7j|djKo0`1F4+6dTP<40OB&ZCXNbGgleeEVs9)%!Z6T$?j`y6qqZa@u z$9rLTbd6jL5QQUYg9Tk#tl|KZYG#oQt@OF*D$W zo;BdZmQjPfyb6Im|JaW1WOl7 zb15(=9&y_m6y*u6%C={6YlJZ81&iyWYlRJq9bhpqe8)tgr8il)j`z4Zy^fA`5)&H; za~f6#uXZBAs}}yj8NK)$0dJi)5L^1>lZR_*EHqG2Lws!wU@TtX5(=$@p4Zpb9xPoE zL)S#s(C%St$js8_=G|vIG30D2-|^A#e*0B|xSMYx_2M42JxLh z_x6t^Y^f(SoGfSpg;1@=B&6Uu?O}rE{T7B-6nIf|bq-1E4D1fTi~2sp8=62dM;&i; zz3|A8SAq9j)@aMiWS1OhlG86J6Z8#+T@q`lju#Kpbtgm0h1Zd}#g+%G6ax67@ht&* z?NB5OwisbLwsnr@VYnb(U*O;Ies`MdOLsE0CMQm7HSD#xR!Tr|l!>q72Q$cvA} zFYexbxS2=L3i7sri3+?RN_mmHkRfz7Wz>Mv+o7He>l%9b&D>7%(PqbKC(~=?uGUF@ z1%@|{++BO}_};yHPoJ;eT)qEtcklke;VtAYd?$f7$QmfBS4(S5)7P1;3%6KE}C6hX_a+a82TurgF*ccntu>X#=;V=IGV@avQ3d%x#>&gy5;Mguo_f6^{_2VY!+ ziw#}tPABU%W%#6`xQjQJWi_zYf4KOR+@HtR$BV&@b94CDeHJ3l_VE(*?uETxehysV zD_8E+bI##IDVj)LkLq7gzpmGh+K(-rjHkPWQ4Jj)FGVg;cvQfP0I`_(;g z8lL_RS{fjl45Av+wH-K+y#QX89nY07zK8?7SUwzZAMT*P{2Y^4>6bjGpALGE8?AOV z&OY}Ce=^-1fVV3oCpw+%6vOUdl9yZ&Z^PAAN}X=9zRY$`35ZBQlbWhFh}t6 zE;8h9OtFwiw>a9OoeHJpmKXD1JY)DW;_*h#Tq8t009~v>*VYiYQEj|@+ZwM!Hc*_D z6ZDgLy!=4$x@U0cPdGA+YL1xtc%2;h2N{x<3#h8MX6iW_h)QHH?GBrRHWH?DND&R9)1uo{?NW2 z=sbYJWtz7+-jeqby4cP@N55ZD3{|o1f+ZK01pu!Gf>(NR+aTOE?81Zl_w$b)fAPgv zfBfPRMDdnHvI{v&LL3-)5xczN@p$9OY5?fMvF;r|00bUyq{(~gu#}vE$jd!p4&9@@ zh8|mnPppQvt!q3aCm=6nZ%m5UgURa`33ol;9bdddYHd}+OPtj-?CkK9I?Vk{|p}k999V774rLcA97=o8d-k=qVAR@Xlq~djjgebIxnvfLaaS}P(zekST?e=)l7VpS-JO1ExsLz1( zC7O5T?!AYP0lYS-TGBN}m_tn)dC83_UTh?TJ2aBPbro)B zufiEM-aT6J`q)O+Dg#VOwt15wwu$UrTqW>#kzCkk222F|w%*GeDl>!g*pvD-sOAuA6nA<{DVKj z?up+B1iSEE5dTmvpXNRTKH~CtgOD80XK{QUdDUB@_&%2<)LuaBa>dL1rMLda4o)Uk zmV^09)Z9YZfFF6R`ih0@$R!(2^8Td9fcH};inoWn;n={FZF=>%XyYL{!2ke!kUU;; z0&k(tUB>(G&qjea+T(R-8yPqP$lW`O*ic3|%Z9e!Sw3`%NYd<9?0k6)^c*DhsKV=8!YR;^?Ib6kaE0^Q2kmKK z01qqLYB=$Dj~J5cv?rnC1PWXlLU06n16~rV0d#I#1MeUcD0o|LqwIS~U>q8pBT9lB z4E0s;9@Ya9?v}^zaHF9w`8im{Hf5MA-Uc88yL;&38b@vrlY`(LiM?yw1xqp>J^95iN-MP*hCYDmZ9vq^_G#V^((d%e2j1#LwQ5dWo2sU!rj*{`_2)7$ z-uZeabA4gXKj`r$%-N}lscY4$`*9VolbD)Kd1Rb1o$0&>5XSNHJJ`Mlql>%2+tcEO zbMTpK?Y|OgXRN+La!$D0)z&~5m}4F<50fR4sPwPO!{_mafnp1^ouNXwyXVqu9G3Hl z=*9ko#g@<7a)G-8wkZs+c()g#>%Hr4!@+N5asgrS78c^St}BYX$73Pct`oEzcuLs_ zfY)ILFJ7c_KRmeqs8A@_#B2cY8VtOA3kCINv)I^>#8$FWNt8xR;YNxu!i`+TNBDkN}ZUPolsPD*6Yo@ zOgWPo&urp+zyQ2k2wp0mt7^(rs^yOi-daNuFwAef)o6^*jL*~o!u8r-0~idm=*Rau z!P`5k0c+rFGOV!k_f%JP&0IUw<2_NlmCh--f31nKUI)orr-~Pm zizo9NMnUm1uYq+oQ1-4oc=*`1VJHva7ElY|)p>W>F5kRXLuzJaK@_j773`vvFKpQQ zE^MPvK=NK%D&z}>MzEX42*?uD{QNT{a7mJ^T0^W6!3&PXHmUOIz-eIjSUp}MHX3sO z-Lsy9MeZI4?>Yl-7?$)&;snD6eEzzgqi=fzp?6yi%x(xZ>|ogCAvp(v(EIjyPtbcH z$J=%3lwraQ?oa;wgYtMCMB5(3;ItZbq^(2ETb{2QqL=L*Zmuq3o7rLut*aO+&OTnJ zV_}UKF>2nT)yzY3(40YImu~tC6K&2VmnJjGs#9QBY26! z6{PXTKV{hQy$|ahI5u4kjuSC~0)2+4KHh@^*9IT`(+28OOUxpA>y)~o)xem`>Jv^G9)0je`hx6=W3sr1EX9EvyRcuoxUoPqaK7VEWlj;{8u zhMqa-!%cS&w@^@cM~`>^X$anV7hhx4B;N*FR+E zpYL^Spy23WF7K#V4d^v+%?m{x2e$-q3Yshn0tc^{mO;ywplsVN6!IGY+Kqg1>D|T# zzQGedDPqQsZWV98$ZPYOwmAFGci#N+jZrGG76YT)c(X}marf@jI%MI~?7=%1^@WHq4C5JQ(( z?26YFc4{z^QQU3zzs5{&US}XLw;BjFSi~E`V{Amg>+sdJw_#VA@6Z3~YggY)u?TASXDp`VO}nRQQHL+*CZ zcRzY@ZS&%Jtcx=-i-*iYW;=H9&U`rsVj5sRcVjaS@_G?%4QDzM4acZrizScOcd5a9 zOehmh8LriK#Vc9Z5-{M*I{J!X7ax2A1=y^i)nGK(`ta@41$Bfm(l|&hIBG!@W#O1*gamye~#Gk za|5Jm(!vq-epgpRcu?Vn9`8t$L)7jTSG=tJl_yU@@rr3H4>I@Wty{Nm-MaLvNwaFI zQqj_k{L(b?c7xo2yZAumYwIb)u!^=u$P3VgLtoR@=I6m{SovQ7uVrLuh&P?rSau0` zd8ivjFCH-{-oG>O@-4$rAvw&UrNwYMU?MO6e$Q0MqZKc}5i9fFi66Y))>h0sKY!tQ zC9_p|e&M1Mi{gbV1aGcw$}mzlSezfOkGFe1Ws4fT$DrcN;|<5-2U~_2al?Ev49OXd zdK>Pdz!ML^mcL?ySS>8y`}W1{OE*8CoURs4NmWuQWp-A%V%SAwE)e(SJNklDK5tuw zZb%5;lD4MJ1Aehecq5v(WEo95X_wC3EdzL|$4lWma7fOH;*AVK$Lg|p;hW70?|tA#m=23Kz%CwV!X#eaiyFrS z3XH~~@e9XK@oq=gmg5~!KI_9n@Rns+NZ`&j23{W002hrZ8x`<6d=Lfm9GL3$f3P1t zd~o;DrJIverkYBnW`Vf-ijqt!FkuZ`1;$&{xi2@~!5zykkuWkz1AhXJHF^Mmk-I6phH?Ir{4<^a4wCLYBuhP)k5#f!UmiFP@@eY~9>Kqq*~=$}Er%Lt9Q4&Z%M zOwQ3=4H>#Ee`djpAH1+^_hszB*nA($1PU&BJ7NvdKf>Pz_A)^C zB^<5%AMZXgMUcxz4s-2GL}Nn~Fq4qZn%E@; z+?5S$iRj#Sw_oDI8Zwu>NALo9ElEq0nkU>PiWkAVf&4IdN_B^P9JL>F}ASmep(%LV>eQxUzWp{ejnS?T=$Bo9j4!u*MqrPxN5ru|Re9 zna5u855fvQWBuXm=fi*IXP^b^eU5+RM1U9T-~b9v$Mza%)MYsPC!($49|qsKc9PZ5 z+0=lFm#+x1wuZ2s?CKC6ubac2Yvt8|yQ8moyZ(QRftP!{=+p#@lVd!cY=q1P4qd!6 z?qcQYH6ZQ|o8&H_+}%&krmXzZGJy8ww?N&O8&HK3a#!QvmBqB2*5H7Xq8G^9KuS=- zi^salr=O$ZJ+?K zIoeJ}sX=2kNs)H4(J6-}HgNO?S!M9tPM*anKS*8S%B}$TP0lKcBoW2?5`6}IwN}7a zC0RuB8j=Rw#bW3M_NISy$wXX&T|gOJE)BZ?#mk|K&#`#38XQNhDyA?A%>A#|aC?0f z!JBlGDJ3Zb(_j2-;6tjz4oAkn2Cce%)iA`CVZ5KB zXILl0E(hPa#`Rh_bB#rKhx8r3tHH-PC1s$l8?o8EPKK&iaUA$gkBy~ND zBSe~TOTwiHkvSnwG%K;7d_sz zwo<2Rm)voh0~|h90A7mT_O6<^x*9wM)+ma`t?ysIf_hEB>zmc2UYnSmO(=@2h>9Pn zckBLf=;L)V7wNwqk~eoKc%wsdI>AfHJ8V}2u)8}Zr^{$K0dGV+88;g6j^O2Sye{8B zf$k&~z8^Y)!p}wXs~)|G0Sv1||Hpp_c>S^;&0XJ#T-+>odc2M=hzVKThf_!>TLXcY zRmYU!U_}ycoE-q(5hE}6cf;-ma&5s`uL+67?hYOC4iS-}F3TF&4UkY)psQ=|UglQ> zfs@y=N=6Bx3)f16h+Qc7svMlu-$i?uYTna41w8~X@pwIdW?`V(b|O69>8ocyza-!M z{`*&;4=8v&^ICP{S`r*ybHc1nOgxWtc+1`~0I%nr-(%*m=U%_=d)^`7jR?t!p1H;q z?1v5+Zr8h^*Km}_J89N1B_$;^D_N7XB2@`q3|Xe75*RcRc;{c%6!EDv5Aa0qo0z(4 zMg+Nt4S-KlsI#}#TGWrEK-hJqlVP!CSOf=EybQZ6o{Y*jKI{_jgZA;36N&LiA(?H| zS`i;NV1+s1MF0V!TN{J`;M$w?iCK}}w`;6!xy4njW) zyw!x65Ea$bE2?Qpa#aDkO^d2w2`R}^v!*GV)r4e8sst$Qw;Z*Slub!d6G_R`tEQl) z40XDqR29{zD5jZ^BquvPZEC6{nr2Fsgh_F->h=V$QO~LH!|*E=LzSkhSyNI>wW=7V zJf*qZDth(P-{Pfw$afM1j%AEc8g#aoFd6ncZ2HrN0xBt;u zQQ>ZIx~!{#>0IiPlRGHhQS+h#NqSPEFc zT~Wr;G)=CR>1GU+pzJ`7`EBWL(8tS@NW-m@6ub)qg7-p{;?<`wUAq0}bFaUD{rbE6 z-%;>Fp-+#ku{CshqrvMO1Ms>RGk!?nbs(?rb%7TbwZaNp8iwp@h}OK!CGLzTW7VJH zRhw2-kPQ`Ns3=MmNrjIp04`mXBt4~CWg}Hnrr}jZHXD_`O9gzZswl|_yrgO>27Gs= zCgWYniq(|rCuG%^EU#)b)ajJ0R#YY12Y4H*K}sz-m~JC1l8zq5ackQ-*n@8ypP3W1|ON=qd|TZ}7yE9q_8$ ztP#zN_!V?pG4hnU1s#R~wRWiH6$x@>S*+E$)`cg3fpQm$r;_3l1ArHbrwg%eXtWxJ z2XENb;BD6~U43=-9B(MYt_HecVjbX%rkLkP$MieL0KDEdv^2B{i1mwe5#S}*jT&~@ zwQp^hV8}2Qva_NTFVHEdPT_Us-RRVNmWWna@NR7iXlp>W}5IytE8lQ z{{WDzRKo-o%HotN2ue*-6d+~YlvS-FN@f-WcA};@N=i+rlB}u;rJ{(v<6r^d<&;!Y zO;J+eH-v;~$aO^oiCZ(_4^f4z;&@6{vSb(ju#{)|rV2*HWL;DM_p;KICsXx~z8{Ae{=trmj!$JvCSmKk_4g%^wAV+6Jg zN82e(+rDkvLQII;cH5pAui@ymT|t%=147YpKwC+~xx?@&kQYDKWHDQRoϑZtp| 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 z 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

    3sP`_l86h=z$fIT_6C4Rc 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 z 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 +

    Heroes examples

    + +
    + +

    Centered hero

    +
    +

    Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.

    +
    + + +
    +
    +
    + +
    + +
    +

    Centered screenshot

    +
    +

    Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.

    +
    + + +
    +
    +
    +
    + Example image +
    +
    +
    + +
    + +
    +
    +
    + Bootstrap Themes +
    +
    +

    Responsive left-aligned hero with image

    +

    Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.

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

    Vertically centered hero sign-up form

    +

    Below is an example form built entirely with Bootstrap’s form controls. Each required form group has a validation state that can be triggered by attempting to submit the form without completing it.

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + +
    + +
    + By clicking Sign up, you agree to the terms of use. +
    +
    +
    +
    + +
    + +
    +
    +
    +

    Border hero with cropped image and shadows

    +

    Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.

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

    Dark color hero

    +
    +

    Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.

    +
    + + +
    +
    +
    +
    + +
    + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotron/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotron/index.astro new file mode 100644 index 00000000..6874af1c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotron/index.astro @@ -0,0 +1,43 @@ +--- +export const title = 'Jumbotron example' +--- + +
    +
    +
    + + Bootstrap + Jumbotron example + +
    + +
    +
    +

    Custom jumbotron

    +

    Using a series of utilities, you can create this jumbotron, just like the one in previous versions of Bootstrap. Check out the examples below for how you can remix and restyle it to your liking.

    + +
    +
    + +
    +
    +
    +

    Change the background

    +

    Swap the background-color utility and add a `.text-*` color utility to mix up the jumbotron look. Then, mix and match with additional component themes and more.

    + +
    +
    +
    +
    +

    Add borders

    +

    Or, keep it light and add a border for some added definition to the boundaries of your content. Be sure to look under the hood at the source HTML here as we've adjusted the alignment and sizing of both column's content for equal-height.

    + +
    +
    +
    + +
    + © {new Date().getFullYear()} +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/index.astro new file mode 100644 index 00000000..587e7930 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/index.astro @@ -0,0 +1,79 @@ +--- +export const title = 'Jumbotrons' +export const extra_css = ['jumbotrons.css'] +--- + + + + Bootstrap + + + + + + + + + + + +
    +
    + +

    Jumbotron with icon

    +

    + This is a custom jumbotron featuring an SVG image at the top, some longer text that wraps early thanks to a responsive .col-* class, and a customized call to action. +

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

    Placeholder jumbotron

    +

    + This faded back jumbotron is useful for placeholder content. It's also a great way to add a bit of context to a page or section when no content is available and to encourage visitors to take a specific action. +

    + +
    +
    + +
    + +
    +
    +
    +

    Full-width jumbotron

    +

    + This takes the basic jumbotron above and makes its background edge-to-edge with a .container inside to align content. Similar to above, it's been recreated with built-in grid and utility classes. +

    +
    +
    +
    + +
    + +
    +
    +

    Basic jumbotron

    +

    + This is a simple Bootstrap jumbotron that sits within a .container, recreated with built-in utility classes. +

    +
    +
    + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/jumbotrons.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/jumbotrons.css new file mode 100644 index 00000000..d7d065ed --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/jumbotrons/jumbotrons.css @@ -0,0 +1 @@ +.border-dashed { --bs-border-style: dashed; } diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/index.astro new file mode 100644 index 00000000..220678f0 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/index.astro @@ -0,0 +1,222 @@ +--- +export const title = 'List groups' +export const extra_css = ['list-groups.css'] +--- + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + + + +
    + +
    + + + +
    +
    + +
    + +
    +
    + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + +
    +
    + +
    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/list-groups.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/list-groups.css new file mode 100644 index 00000000..b90cfa06 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/list-groups/list-groups.css @@ -0,0 +1,63 @@ +.list-group { + width: 100%; + max-width: 460px; + margin-inline: 1.5rem; +} + +.form-check-input:checked + .form-checked-content { + opacity: .5; +} + +.form-check-input-placeholder { + border-style: dashed; +} +[contenteditable]:focus { + outline: 0; +} + +.list-group-checkable .list-group-item { + cursor: pointer; +} +.list-group-item-check { + position: absolute; + clip: rect(0, 0, 0, 0); +} +.list-group-item-check:hover + .list-group-item { + background-color: var(--bs-secondary-bg); +} +.list-group-item-check:checked + .list-group-item { + color: #fff; + background-color: var(--bs-primary); + border-color: var(--bs-primary); +} +.list-group-item-check[disabled] + .list-group-item, +.list-group-item-check:disabled + .list-group-item { + pointer-events: none; + filter: none; + opacity: .5; +} + +.list-group-radio .list-group-item { + cursor: pointer; + border-radius: .5rem; +} +.list-group-radio .form-check-input { + z-index: 2; + margin-top: -.5em; +} +.list-group-radio .list-group-item:hover, +.list-group-radio .list-group-item:focus { + background-color: var(--bs-secondary-bg); +} + +.list-group-radio .form-check-input:checked + .list-group-item { + background-color: var(--bs-body); + border-color: var(--bs-primary); + box-shadow: 0 0 0 2px var(--bs-primary); +} +.list-group-radio .form-check-input[disabled] + .list-group-item, +.list-group-radio .form-check-input:disabled + .list-group-item { + pointer-events: none; + filter: none; + opacity: .5; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/masonry/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/masonry/index.astro new file mode 100644 index 00000000..58aea3f1 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/masonry/index.astro @@ -0,0 +1,106 @@ +--- +export const title = 'Masonry example' +export const extra_js = [{ + src: 'https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js', + integrity: 'sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D', + async: true +}] +import Placeholder from "@shortcodes/Placeholder.astro" +--- + +
    +

    Bootstrap and Masonry

    +

    Integrate Masonry with the Bootstrap grid system and cards component.

    + +

    Masonry is not included in Bootstrap. Add it by including the JavaScript plugin manually, or using a CDN like so:

    + +
    
    +<script src="https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" crossorigin="anonymous" async></script>
    +  
    + +

    By adding data-masonry='}"percentPosition": true }' to the .row wrapper, we can combine the powers of Bootstrap's responsive grid and Masonry's positioning.

    + +
    + +
    +
    +
    + +
    +
    Card title that wraps to a new line
    +

    This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

    +
    +
    +
    +
    +
    +
    +
    +

    A well-known quote, contained in a blockquote element.

    +
    + +
    +
    +
    +
    +
    + +
    +
    Card title
    +

    This card has supporting text below as a natural lead-in to additional content.

    +

    Last updated 3 mins ago

    +
    +
    +
    +
    +
    +
    +
    +

    A well-known quote, contained in a blockquote element.

    +
    + +
    +
    +
    +
    +
    +
    +
    Card title
    +

    This card has a regular title and short paragraph of text below it.

    +

    Last updated 3 mins ago

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

    A well-known quote, contained in a blockquote element.

    +
    + +
    +
    +
    +
    +
    +
    +
    Card title
    +

    This is another card with title and supporting text below. This card has some additional content to make it slightly taller overall.

    +

    Last updated 3 mins ago

    +
    +
    +
    +
    + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/index.astro new file mode 100644 index 00000000..9514f6f1 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/index.astro @@ -0,0 +1,147 @@ +--- +export const title = 'Modals' +export const extra_css = ['modals.css'] +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + + + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/modals.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/modals.css new file mode 100644 index 00000000..194e16ac --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/modals/modals.css @@ -0,0 +1,7 @@ +.modal-sheet .modal-dialog { + width: 380px; + transition: bottom .75s ease-in-out; +} +.modal-sheet .modal-footer { + padding-bottom: 2rem; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-bottom/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-bottom/index.astro new file mode 100644 index 00000000..35aa348c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-bottom/index.astro @@ -0,0 +1,42 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Bottom navbar example' +--- + +
    +
    +

    Bottom Navbar example

    +

    This example is a quick exercise to illustrate how the bottom navbar works.

    + View navbar docs » +
    +
    + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/index.astro new file mode 100644 index 00000000..3524255c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/index.astro @@ -0,0 +1,40 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Fixed top navbar example' +export const extra_css = ['navbar-fixed.css'] +--- + + + +
    +
    +

    Navbar example

    +

    This example is a quick exercise to illustrate how fixed to top navbar works. As you scroll, it will remain fixed to the top of your browser’s viewport.

    + View navbar docs » +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/navbar-fixed.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/navbar-fixed.css new file mode 100644 index 00000000..c77c0c14 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-fixed/navbar-fixed.css @@ -0,0 +1,5 @@ +/* Show it is fixed to the top */ +body { + min-height: 75rem; + padding-top: 4.5rem; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/index.astro new file mode 100644 index 00000000..600b313e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/index.astro @@ -0,0 +1,40 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Top navbar example' +export const extra_css = ['navbar-static.css'] +--- + + + +
    +
    +

    Navbar example

    +

    This example is a quick exercise to illustrate how the top-aligned navbar works. As you scroll, this navbar remains in its original position and moves with the rest of the page.

    + View navbar docs » +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/navbar-static.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/navbar-static.css new file mode 100644 index 00000000..25bbdde0 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbar-static/navbar-static.css @@ -0,0 +1,4 @@ +/* Show it's not fixed to the top */ +body { + min-height: 75rem; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/index.astro new file mode 100644 index 00000000..ec6b03f7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/index.astro @@ -0,0 +1,147 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Navbar Template' +export const extra_css = ['navbars-offcanvas.css'] +--- + +
    + + + + + + +
    +
    +
    +

    Navbar with offcanvas examples

    +

    This example shows how responsive offcanvas menus work within the navbar. For positioning of navbars, checkout the top and fixed top examples.

    +

    From the top down, you'll see a dark navbar, light navbar and a responsive navbar—each with offcanvases built in. Resize your browser window to the large breakpoint to see the toggle for the offcanvas.

    +

    + Learn more about offcanvas navbars » +

    +
    +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/navbars-offcanvas.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/navbars-offcanvas.css new file mode 100644 index 00000000..70d20940 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars-offcanvas/navbars-offcanvas.css @@ -0,0 +1,7 @@ +body { + padding-bottom: 20px; +} + +.navbar { + margin-bottom: 20px; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/index.astro new file mode 100644 index 00000000..c48993f8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/index.astro @@ -0,0 +1,450 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Navbar Template' +export const extra_css = ['navbars.css'] +--- + +
    + + + + + + + + + + + + + + + + + + +
    +

    Matching .container-xl...

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

    Navbar examples

    +

    This example is a quick exercise to illustrate how the navbar and its contents work. Some navbars extend the width of the viewport, others are confined within a .container. For positioning of navbars, checkout the top and fixed top examples.

    +

    At the smallest breakpoint, the collapse plugin is used to hide the links and show a menu button to toggle the collapsed content.

    +

    + View navbar docs » +

    +
    +
    +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/navbars.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/navbars.css new file mode 100644 index 00000000..70d20940 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/navbars/navbars.css @@ -0,0 +1,7 @@ +body { + padding-bottom: 20px; +} + +.navbar { + margin-bottom: 20px; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/index.astro new file mode 100644 index 00000000..ac94ca88 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/index.astro @@ -0,0 +1,140 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Offcanvas navbar template' +export const extra_css = ['offcanvas-navbar.css'] +export const extra_js = [{ src: 'offcanvas-navbar.js' }] +export const body_class = 'bg-body-tertiary' +export const aliases = '/docs/[[config:docs_version]]/examples/offcanvas/' +import Placeholder from "@shortcodes/Placeholder.astro" +--- + + + + + +
    +
    + +
    +

    Bootstrap

    + Since 2011 +
    +
    + +
    +
    Recent updates
    +
    + +

    + @username + Some representative placeholder content, with some information about this user. Imagine this being some sort of status update, perhaps? +

    +
    +
    + +

    + @username + Some more representative placeholder content, related to this other user. Another status update, perhaps. +

    +
    +
    + +

    + @username + This user also gets some representative placeholder content. Maybe they did something interesting, and you really want to highlight this in the recent updates. +

    +
    + + All updates + +
    + +
    +
    Suggestions
    +
    + +
    +
    + Full Name + Follow +
    + @username +
    +
    +
    + +
    +
    + Full Name + Follow +
    + @username +
    +
    +
    + +
    +
    + Full Name + Follow +
    + @username +
    +
    + + All suggestions + +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.css new file mode 100644 index 00000000..f855b96a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.css @@ -0,0 +1,52 @@ +html, +body { + overflow-x: hidden; /* Prevent scroll on narrow devices */ +} + +body { + padding-top: 56px; +} + +@media (max-width: 991.98px) { + .offcanvas-collapse { + position: fixed; + top: 56px; /* Height of navbar */ + bottom: 0; + left: 100%; + width: 100%; + padding-right: 1rem; + padding-left: 1rem; + overflow-y: auto; + visibility: hidden; + background-color: #343a40; + transition: transform .3s ease-in-out, visibility .3s ease-in-out; + } + .offcanvas-collapse.open { + visibility: visible; + transform: translateX(-100%); + } +} + +.nav-scroller .nav { + color: rgba(255, 255, 255, .75); +} + +.nav-scroller .nav-link { + padding-top: .75rem; + padding-bottom: .75rem; + font-size: .875rem; + color: #6c757d; +} + +.nav-scroller .nav-link:hover { + color: #007bff; +} + +.nav-scroller .active { + font-weight: 500; + color: #343a40; +} + +.bg-purple { + background-color: #6f42c1; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.js new file mode 100644 index 00000000..b97a1716 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/offcanvas-navbar/offcanvas-navbar.js @@ -0,0 +1,7 @@ +(() => { + 'use strict' + + document.querySelector('#navbarSideCollapse').addEventListener('click', () => { + document.querySelector('.offcanvas-collapse').classList.toggle('open') + }) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/index.astro new file mode 100644 index 00000000..e51668fc --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/index.astro @@ -0,0 +1,186 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Pricing example' +export const extra_css = ['pricing.css'] +--- + + + + Check + + + + +
    +
    + + +
    +

    Pricing

    +

    Quickly build an effective pricing table for your potential customers with this Bootstrap example. It’s built with default Bootstrap components and utilities with little customization.

    +
    +
    + +
    +
    +
    +
    +
    +

    Free

    +
    +
    +

    $0/mo

    +
      +
    • 10 users included
    • +
    • 2 GB of storage
    • +
    • Email support
    • +
    • Help center access
    • +
    + +
    +
    +
    +
    +
    +
    +

    Pro

    +
    +
    +

    $15/mo

    +
      +
    • 20 users included
    • +
    • 10 GB of storage
    • +
    • Priority email support
    • +
    • Help center access
    • +
    + +
    +
    +
    +
    +
    +
    +

    Enterprise

    +
    +
    +

    $29/mo

    +
      +
    • 30 users included
    • +
    • 15 GB of storage
    • +
    • Phone and email support
    • +
    • Help center access
    • +
    + +
    +
    +
    +
    + +

    Compare plans

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FreeProEnterprise
    Public
    Private
    Permissions
    Sharing
    Unlimited members
    Extra security
    +
    +
    + + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/pricing.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/pricing.css new file mode 100644 index 00000000..c65d0208 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/pricing/pricing.css @@ -0,0 +1,11 @@ +body { + background-image: linear-gradient(180deg, var(--bs-secondary-bg), var(--bs-body-bg) 100px, var(--bs-body-bg)); +} + +.container { + max-width: 960px; +} + +.pricing-header { + max-width: 700px; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/index.astro new file mode 100644 index 00000000..7c98d11a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/index.astro @@ -0,0 +1,187 @@ +--- +export const title = 'Product example' +export const extra_css = ['product.css'] +--- + + + + + + + + + + + + + + + + +
    +
    +
    +

    Designed for engineers

    +

    Build anything you want with Aperture

    + +
    +
    +
    +
    + +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    + +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    + +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    + +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    +
    +

    Another headline

    +

    And an even wittier subheading.

    +
    +
    +
    +
    +
    + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/product.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/product.css new file mode 100644 index 00000000..6c90ae51 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/product/product.css @@ -0,0 +1,74 @@ +.container { + max-width: 960px; +} + +.icon-link > .bi { + width: .75em; + height: .75em; +} + +/* + * Custom translucent site header + */ + +.site-header { + background-color: rgba(0, 0, 0, .85); + -webkit-backdrop-filter: saturate(180%) blur(20px); + backdrop-filter: saturate(180%) blur(20px); +} +.site-header a { + color: #8e8e8e; + transition: color .15s ease-in-out; +} +.site-header a:hover { + color: #fff; + text-decoration: none; +} + +/* + * Dummy devices (replace them with your own or something else entirely!) + */ + +.product-device { + position: absolute; + right: 10%; + bottom: -30%; + width: 300px; + height: 540px; + background-color: #333; + border-radius: 21px; + transform: rotate(30deg); +} + +.product-device::before { + position: absolute; + top: 10%; + right: 10px; + bottom: 10%; + left: 10px; + content: ""; + background-color: rgba(255, 255, 255, .1); + border-radius: 5px; +} + +.product-device-2 { + top: -25%; + right: auto; + bottom: 0; + left: 5%; + background-color: #e5e5e5; +} + + +/* + * Extra utilities + */ + +.flex-equal > * { + flex: 1; +} +@media (min-width: 768px) { + .flex-md-equal > * { + flex: 1; + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/index.astro new file mode 100644 index 00000000..de67a80b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/index.astro @@ -0,0 +1,352 @@ +--- +export const title = 'Sidebars' +export const extra_css = ['sidebars.css'] +export const extra_js = [{src: 'sidebars.js'}] +--- + + + + Bootstrap + + + + + + + + + + + + + + + + + + + + + +
    +

    Sidebars examples

    + + + +
    + + + +
    + +
    + + + Icon-only + + + +
    + +
    + +
    + + + Collapsible + + +
    + +
    + + + +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.css new file mode 100644 index 00000000..f6a8f1c5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.css @@ -0,0 +1,63 @@ +body { + min-height: 100vh; + min-height: -webkit-fill-available; +} + +html { + height: -webkit-fill-available; +} + +main { + height: 100vh; + height: -webkit-fill-available; + max-height: 100vh; + overflow-x: auto; + overflow-y: hidden; +} + +.dropdown-toggle { outline: 0; } + +.btn-toggle { + padding: .25rem .5rem; + font-weight: 600; + color: var(--bs-emphasis-color); + background-color: transparent; +} +.btn-toggle:hover, +.btn-toggle:focus { + color: rgba(var(--bs-emphasis-color-rgb), .85); + background-color: var(--bs-tertiary-bg); +} + +.btn-toggle::before { + width: 1.25em; + line-height: 0; + content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); + transition: transform .35s ease; + transform-origin: .5em 50%; +} + +[data-bs-theme="dark"] .btn-toggle::before { + content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28255,255,255,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); +} + +.btn-toggle[aria-expanded="true"] { + color: rgba(var(--bs-emphasis-color-rgb), .85); +} +.btn-toggle[aria-expanded="true"]::before { + transform: rotate(90deg); +} + +.btn-toggle-nav a { + padding: .1875rem .5rem; + margin-top: .125rem; + margin-left: 1.25rem; +} +.btn-toggle-nav a:hover, +.btn-toggle-nav a:focus { + background-color: var(--bs-tertiary-bg); +} + +.scrollarea { + overflow-y: auto; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.js new file mode 100644 index 00000000..4075f1f1 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sidebars/sidebars.js @@ -0,0 +1,8 @@ +/* global bootstrap: false */ +(() => { + 'use strict' + const tooltipTriggerList = Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]')) + tooltipTriggerList.forEach(tooltipTriggerEl => { + new bootstrap.Tooltip(tooltipTriggerEl) + }) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/index.astro new file mode 100644 index 00000000..ffbd75b9 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/index.astro @@ -0,0 +1,32 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Signin Template' +export const extra_css = ['sign-in.css'] +export const body_class = 'd-flex align-items-center py-4 bg-body-tertiary' +--- + +
    +
    + +

    Please sign in

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

    © 2017–{new Date().getFullYear()}

    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/sign-in.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/sign-in.css new file mode 100644 index 00000000..641f6d90 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sign-in/sign-in.css @@ -0,0 +1,25 @@ +html, +body { + height: 100%; +} + +.form-signin { + max-width: 330px; + padding: 1rem; +} + +.form-signin .form-floating:focus-within { + z-index: 2; +} + +.form-signin input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.form-signin input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/starter-template/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/starter-template/index.astro new file mode 100644 index 00000000..0af31653 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/starter-template/index.astro @@ -0,0 +1,108 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Starter Template' +--- + + + + + + + Bootstrap + + + + +
    +
    + + + Starter template + +
    + +
    +

    Get started with Bootstrap

    +

    Quickly and easily get started with Bootstrap's compiled, production-ready files with this barebones example featuring some basic HTML and helpful links. Download all our examples to get started.

    + + + +
    + +
    +
    +

    Starter projects

    +

    Ready to go beyond the starter template? Check out these open source projects that you can quickly duplicate to a new GitHub repository.

    + +
    + +
    +

    Guides

    +

    Read more detailed instructions and documentation on using or contributing to Bootstrap.

    + +
    +
    +
    +
    + Created by the Bootstrap team · © {new Date().getFullYear()} +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/index.astro new file mode 100644 index 00000000..9b9b5ebb --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/index.astro @@ -0,0 +1,52 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Sticky Footer Navbar Template' +export const extra_css = ['sticky-footer-navbar.css'] +export const html_class = 'h-100' +export const body_class = 'd-flex flex-column h-100' +--- + +
    + + +
    + + +
    +
    +

    Sticky footer with fixed navbar

    +

    Pin a footer to the bottom of the viewport in desktop browsers with this custom HTML and CSS. A fixed navbar has been added with padding-top: 60px; on the main > .container.

    +

    Back to the default sticky footer minus the navbar.

    +
    +
    + +
    +
    + Place sticky footer content here. +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/sticky-footer-navbar.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/sticky-footer-navbar.css new file mode 100644 index 00000000..3087ead7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer-navbar/sticky-footer-navbar.css @@ -0,0 +1,7 @@ +/* Custom page CSS +-------------------------------------------------- */ +/* Not required for template or sticky footer method. */ + +main > .container { + padding: 60px 15px 0; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/index.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/index.astro new file mode 100644 index 00000000..b436ad0c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/index.astro @@ -0,0 +1,23 @@ +--- +import { getVersionedDocsPath } from '@libs/path' + +export const title = 'Sticky Footer Template' +export const extra_css = ['sticky-footer.css'] +export const html_class = 'h-100' +export const body_class = 'd-flex flex-column h-100' +--- + + +
    +
    +

    Sticky footer

    +

    Pin a footer to the bottom of the viewport in desktop browsers with this custom HTML and CSS.

    +

    Use the sticky footer with a fixed navbar if need be, too.

    +
    +
    + +
    +
    + Place sticky footer content here. +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/sticky-footer.css b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/sticky-footer.css new file mode 100644 index 00000000..f8be4372 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/sticky-footer/sticky-footer.css @@ -0,0 +1,9 @@ +/* Custom page CSS +-------------------------------------------------- */ +/* Not required for template or sticky footer method. */ + +.container { + width: auto; + max-width: 680px; + padding: 0 15px; +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/sidebar.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/sidebar.js new file mode 100644 index 00000000..bf42e7b5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/sidebar.js @@ -0,0 +1,30 @@ +// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT +// IT'S ALL JUST JUNK FOR OUR DOCS! +// ++++++++++++++++++++++++++++++++++++++++++ + +/* + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +export default () => { + // Scroll the active sidebar link into view + const sidenav = document.querySelector('.bd-sidebar') + const sidenavActiveLink = document.querySelector('.bd-links-nav .active') + + if (!sidenav || !sidenavActiveLink) { + return + } + + const sidenavHeight = sidenav.clientHeight + const sidenavActiveLinkTop = sidenavActiveLink.offsetTop + const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight + const viewportTop = sidenavActiveLinkTop + const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight + + if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) { + sidenav.scrollTop = viewportTop - (sidenavHeight / 2) + (sidenavActiveLinkHeight / 2) + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/snippets.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/snippets.js new file mode 100644 index 00000000..498071b4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/partials/snippets.js @@ -0,0 +1,168 @@ +// NOTICE!!! Initially embedded in our docs this JavaScript +// file contains elements that can help you create reproducible +// use cases in StackBlitz for instance. +// In a real project please adapt this content to your needs. +// ++++++++++++++++++++++++++++++++++++++++++ + +/* + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +/* global bootstrap: false */ + +export default () => { + // -------- + // Tooltips + // -------- + // Instantiate all tooltips in a docs or StackBlitz + document.querySelectorAll('[data-bs-toggle="tooltip"]') + .forEach(tooltip => { + new bootstrap.Tooltip(tooltip) + }) + + // -------- + // Popovers + // -------- + // Instantiate all popovers in docs or StackBlitz + document.querySelectorAll('[data-bs-toggle="popover"]') + .forEach(popover => { + new bootstrap.Popover(popover) + }) + + // ------------------------------- + // Toasts + // ------------------------------- + // Used by 'Placement' example in docs or StackBlitz + const toastPlacement = document.getElementById('toastPlacement') + if (toastPlacement) { + document.getElementById('selectToastPlacement').addEventListener('change', function () { + if (!toastPlacement.dataset.originalClass) { + toastPlacement.dataset.originalClass = toastPlacement.className + } + + toastPlacement.className = `${toastPlacement.dataset.originalClass} ${this.value}` + }) + } + + // Instantiate all toasts in docs pages only + document.querySelectorAll('.bd-example .toast') + .forEach(toastNode => { + const toast = new bootstrap.Toast(toastNode, { + autohide: false + }) + + toast.show() + }) + + // Instantiate all toasts in docs pages only + // js-docs-start live-toast + const toastTrigger = document.getElementById('liveToastBtn') + const toastLiveExample = document.getElementById('liveToast') + + if (toastTrigger) { + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastTrigger.addEventListener('click', () => { + toastBootstrap.show() + }) + } + // js-docs-end live-toast + + // ------------------------------- + // Alerts + // ------------------------------- + // Used in 'Show live alert' example in docs or StackBlitz + + // js-docs-start live-alert + const alertPlaceholder = document.getElementById('liveAlertPlaceholder') + const appendAlert = (message, type) => { + const wrapper = document.createElement('div') + wrapper.innerHTML = [ + `' + ].join('') + + alertPlaceholder.append(wrapper) + } + + const alertTrigger = document.getElementById('liveAlertBtn') + if (alertTrigger) { + alertTrigger.addEventListener('click', () => { + appendAlert('Nice, you triggered this alert message!', 'success') + }) + } + // js-docs-end live-alert + + // -------- + // Carousels + // -------- + // Instantiate all non-autoplaying carousels in docs or StackBlitz + document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])') + .forEach(carousel => { + bootstrap.Carousel.getOrCreateInstance(carousel) + }) + + // ------------------------------- + // Checks & Radios + // ------------------------------- + // Indeterminate checkbox example in docs and StackBlitz + document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]') + .forEach(checkbox => { + if (checkbox.id.includes('Indeterminate')) { + checkbox.indeterminate = true + } + }) + + // ------------------------------- + // Links + // ------------------------------- + // Disable empty links in docs examples only + document.querySelectorAll('.bd-content [href="#"]') + .forEach(link => { + link.addEventListener('click', event => { + event.preventDefault() + }) + }) + + // ------------------------------- + // Modal + // ------------------------------- + // Modal 'Varying modal content' example in docs and StackBlitz + // js-docs-start varying-modal-content + const exampleModal = document.getElementById('exampleModal') + if (exampleModal) { + exampleModal.addEventListener('show.bs.modal', event => { + // Button that triggered the modal + const button = event.relatedTarget + // Extract info from data-bs-* attributes + const recipient = button.getAttribute('data-bs-whatever') + // If necessary, you could initiate an Ajax request here + // and then do the updating in a callback. + + // Update the modal's content. + const modalTitle = exampleModal.querySelector('.modal-title') + const modalBodyInput = exampleModal.querySelector('.modal-body input') + + modalTitle.textContent = `New message to ${recipient}` + modalBodyInput.value = recipient + }) + } + // js-docs-end varying-modal-content + + // ------------------------------- + // Offcanvas + // ------------------------------- + // 'Offcanvas components' example in docs only + const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas') + if (myOffcanvas) { + myOffcanvas.forEach(offcanvas => { + offcanvas.addEventListener('show.bs.offcanvas', event => { + event.preventDefault() + }, false) + }) + } +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/search.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/search.js new file mode 100644 index 00000000..1077babd --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/search.js @@ -0,0 +1,59 @@ +// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT +// IT'S ALL JUST JUNK FOR OUR DOCS! +// ++++++++++++++++++++++++++++++++++++++++++ + +/*! + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2024-2025 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +import docsearch from '@docsearch/js' + +(() => { + // These values will be replaced by Astro's Vite plugin + const CONFIG = { + apiKey: '__API_KEY__', + indexName: '__INDEX_NAME__', + appId: '__APP_ID__' + } + + const searchElement = document.getElementById('docsearch') + + if (!searchElement) { + return + } + + const siteDocsVersion = searchElement.getAttribute('data-bd-docs-version') + + docsearch({ + apiKey: CONFIG.apiKey, + indexName: CONFIG.indexName, + appId: CONFIG.appId, + container: searchElement, + searchParameters: { + facetFilters: [`version:${siteDocsVersion}`] + }, + transformItems(items) { + return items.map(item => { + const liveUrl = 'https://getbootstrap.com/' + + item.url = window.location.origin.startsWith(liveUrl) ? + // On production, return the result as is + item.url : + // On development or Netlify, replace `item.url` with a trailing slash, + // so that the result link is relative to the server root + item.url.replace(liveUrl, '/') + + // Prevent jumping to first header + if (item.anchor === 'content') { + item.url = item.url.replace(/#content$/, '') + item.anchor = null + } + + return item + }) + } + }) +})() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/snippets.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/snippets.js new file mode 100644 index 00000000..d18ab41c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/snippets.js @@ -0,0 +1,15 @@ +/* + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +// Note that this file is not published; we only include it in scripts.html +// for StackBlitz to work + +/* eslint-disable import/no-unresolved */ +import snippets from 'js/partials/snippets.js' +/* eslint-enable import/no-unresolved */ + +snippets() diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/stackblitz.js b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/stackblitz.js new file mode 100644 index 00000000..0b450a7d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/stackblitz.js @@ -0,0 +1,89 @@ +// NOTICE!!! Initially embedded in our docs this JavaScript +// file contains elements that can help you create reproducible +// use cases in StackBlitz for instance. +// In a real project please adapt this content to your needs. +// ++++++++++++++++++++++++++++++++++++++++++ + +/*! + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2024-2025 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +import sdk from '@stackblitz/sdk' +// eslint-disable-next-line import/no-unresolved +import snippetsContent from './partials/snippets.js?raw' + +// These values will be replaced by Astro's Vite plugin +const CONFIG = { + cssCdn: '__CSS_CDN__', + jsBundleCdn: '__JS_BUNDLE_CDN__', + docsVersion: '__DOCS_VERSION__' +} + +// Open in StackBlitz logic +document.querySelectorAll('.btn-edit').forEach(btn => { + btn.addEventListener('click', event => { + const codeSnippet = event.target.closest('.bd-code-snippet') + const exampleEl = codeSnippet.querySelector('.bd-example') + + const htmlSnippet = exampleEl.innerHTML + const jsSnippet = codeSnippet.querySelector('.btn-edit').getAttribute('data-sb-js-snippet') + // Get extra classes for this example + const classes = Array.from(exampleEl.classList).join(' ') + + openBootstrapSnippet(htmlSnippet, jsSnippet, classes) + }) +}) + +const openBootstrapSnippet = (htmlSnippet, jsSnippet, classes) => { + const indexHtml = ` + + + + + + + Bootstrap Example + + + + +${htmlSnippet.trimStart().replace(/^/gm, ' ').replace(/^ {4}$/gm, '').trimEnd()} + + +` + + // Modify the snippets content to convert export default to a variable and invoke it + let modifiedSnippetsContent = '' + + if (jsSnippet) { + // Replace export default with a variable assignment + modifiedSnippetsContent = snippetsContent.replace( + 'export default () => {', + 'const snippets_default = () => {' + ) + + // Add IIFE wrapper and execution + modifiedSnippetsContent = `(() => { + ${modifiedSnippetsContent} + + // + snippets_default(); +})();` + } + + const project = { + files: { + 'index.html': indexHtml, + ...(jsSnippet && { 'index.js': modifiedSnippetsContent }) + }, + title: 'Bootstrap Example', + description: `Official example from ${window.location.href}`, + template: jsSnippet ? 'javascript' : 'html', + tags: ['bootstrap'] + } + + sdk.openProject(project, { openFile: 'index.html' }) +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Ads.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Ads.astro new file mode 100644 index 00000000..2a53c0a6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Ads.astro @@ -0,0 +1,9 @@ +--- +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/DocsSidebar.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/DocsSidebar.astro new file mode 100644 index 00000000..1282ed70 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/DocsSidebar.astro @@ -0,0 +1,84 @@ +--- +import { getData } from '@libs/data' +import { getConfig } from '@libs/config' +import { docsPages } from '@libs/content' +import { getSlug } from '@libs/utils' + +const sidebar = getData('sidebar') +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Scripts.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Scripts.astro new file mode 100644 index 00000000..b17057d2 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/Scripts.astro @@ -0,0 +1,17 @@ +--- +import { getVersionedBsJsProps } from '@libs/bootstrap' +import type { Layout } from '@libs/layout' + +interface Props { + layout: Layout +} + +const { layout } = Astro.props +--- + + + + + + +{layout === 'docs' && diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Favicons.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Favicons.astro new file mode 100644 index 00000000..9c462c90 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Favicons.astro @@ -0,0 +1,11 @@ +--- +import { getVersionedDocsPath } from '@libs/path' +--- + + + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Head.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Head.astro new file mode 100644 index 00000000..434ba835 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Head.astro @@ -0,0 +1,54 @@ +--- +import { getConfig } from '@libs/config' +import { getVersionedDocsPath } from '@libs/path' +import type { Layout } from '@libs/layout' +import Stylesheet from '@components/head/Stylesheet.astro' +import Favicons from '@components/head/Favicons.astro' +import Social from '@components/head/Social.astro' +import Analytics from '@components/head/Analytics.astro' +import Scss from '@components/head/Scss.astro' + +interface Props { + description: string + direction?: 'rtl' + layout: Layout + robots: string | undefined + thumbnail: string + title: string +} + +const { description, direction, layout, robots, thumbnail, title } = Astro.props + +const canonicalUrl = new URL(Astro.url.pathname, Astro.site) + +const isHome = Astro.url.pathname === '/' +const pageTitle = isHome + ? `${getConfig().title} · ${getConfig().subtitle}` + : `${title} · ${getConfig().title} v${getConfig().docs_version}` +--- + + + + + + + + + + + + + + + +{pageTitle} + +{robots && } + + + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Scss.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Scss.astro new file mode 100644 index 00000000..fc10fe75 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Scss.astro @@ -0,0 +1,7 @@ +--- +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Social.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Social.astro new file mode 100644 index 00000000..bf97d1e8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Social.astro @@ -0,0 +1,31 @@ +--- +import { getConfig } from '@libs/config' +import { getVersionedDocsPath } from '@libs/path' +import { getStaticImageSize } from '@libs/image' +import type { Layout } from '@libs/layout' + +interface Props { + description: string + layout: Layout + thumbnail: string + title: string +} + +const { description, layout, thumbnail, title } = Astro.props + +const socialImageUrl = new URL(getVersionedDocsPath(`assets/${thumbnail}`), Astro.site) +const socialImageSize = await getStaticImageSize(`/docs/[version]/assets/${thumbnail}`) +--- + + + + + + + + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Stylesheet.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Stylesheet.astro new file mode 100644 index 00000000..d0203893 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/head/Stylesheet.astro @@ -0,0 +1,13 @@ +--- +import { getVersionedBsCssProps } from '@libs/bootstrap' +import type { Layout } from '@libs/layout' + +interface Props { + direction?: 'rtl' + layout: Layout +} + +const { direction } = Astro.props +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Header.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Header.astro new file mode 100644 index 00000000..e68b160a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Header.astro @@ -0,0 +1,20 @@ +--- +import type { CollectionEntry } from 'astro:content' +import type { Layout } from '@libs/layout' +import Skippy from '@components/header/Skippy.astro' +import Symbols from '@components/icons/Symbols.astro' +import Navigation from '@components/header/Navigation.astro' + +interface Props { + addedIn?: CollectionEntry<'docs'>['data']['added'] + layout: Layout + title: string +} + +const { addedIn, layout, title } = Astro.props +--- + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/LinkItem.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/LinkItem.astro new file mode 100644 index 00000000..0b3f42f5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/LinkItem.astro @@ -0,0 +1,24 @@ +--- +interface Props { + active?: boolean + class?: string + href: string + rel?: HTMLAnchorElement['rel'] + target?: HTMLAnchorElement['target'] + track?: boolean +} + +const { active, class: className, track, ...props } = Astro.props + +const content = await Astro.slots.render('default') +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Navigation.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Navigation.astro new file mode 100644 index 00000000..4e55d54f --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Navigation.astro @@ -0,0 +1,131 @@ +--- +import type { CollectionEntry } from 'astro:content' +import { getConfig } from '@libs/config' +import { getVersionedDocsPath } from '@libs/path' +import type { Layout } from '@libs/layout' +import BootstrapWhiteFillIcon from '@components/icons/BootstrapWhiteFillIcon.astro' +import GitHubIcon from '@components/icons/GitHubIcon.astro' +import HamburgerIcon from '@components/icons/HamburgerIcon.astro' +import LinkItem from '@components/header/LinkItem.astro' +import OpenCollectiveIcon from '@components/icons/OpenCollectiveIcon.astro' +import XIcon from '@components/icons/XIcon.astro' +import Versions from '@components/header/Versions.astro' +import ThemeToggler from '@layouts/partials/ThemeToggler.astro' + +interface Props { + addedIn?: CollectionEntry<'docs'>['data']['added'] + layout: Layout + title: string +} + +const { addedIn, layout, title } = Astro.props +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Skippy.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Skippy.astro new file mode 100644 index 00000000..aa5ba1db --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Skippy.astro @@ -0,0 +1,22 @@ +--- +import type { Layout } from '@libs/layout' + +interface Props { + layout: Layout +} + +const { layout } = Astro.props +--- + +
    +
    + Skip to main content + { + layout === 'docs' && ( + + Skip to docs navigation + + ) + } +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Versions.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Versions.astro new file mode 100644 index 00000000..a1119e0a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/header/Versions.astro @@ -0,0 +1,96 @@ +--- +import type { CollectionEntry } from 'astro:content' +import { getConfig } from '@libs/config' +import type { Layout } from '@libs/layout' +import { getVersionedDocsPath } from '@libs/path' + +interface Props { + addedIn?: CollectionEntry<'docs'>['data']['added'] + layout: Layout +} + +const { addedIn, layout } = Astro.props +const { slug, version } = Astro.params + +const isHome = Astro.url.pathname === '/' + +let versionsLink = '' + +if (layout === 'docs' && version === getConfig().docs_version) { + versionsLink = `${slug}/` +} else if (layout === 'single' && Astro.url.pathname.startsWith(getVersionedDocsPath(''))) { + versionsLink = Astro.url.pathname.replace(getVersionedDocsPath(''), '') +} + +const addedIn51 = addedIn?.version === '5.1' +const addedIn52 = addedIn?.version === '5.2' +const addedIn53 = addedIn?.version === '5.3' +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/CSSVariables.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/CSSVariables.astro new file mode 100644 index 00000000..92dad9dd --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/CSSVariables.astro @@ -0,0 +1,71 @@ +--- +import { getVersionedDocsPath } from '@libs/path' +import Code from '@shortcodes/Code.astro' +--- + +
    +
    +
    + +
    +

    Build and extend in real-time with CSS variables

    +

    + Bootstrap 5 is evolving with each release to better utilize CSS variables for global theme styles, individual + components, and even utilities. We provide dozens of variables for colors, font styles, and more at a :root level for use anywhere. On components and utilities, CSS variables are scoped to the relevant class and can easily + be modified. +

    +

    + + Learn more about CSS variables + + +

    +
    +
    +
    +

    Using CSS variables

    +

    + Use any of our global :root variables to write new styles. CSS variables use the var(--bs-variableName) syntax and can be inherited by children + elements. +

    + +
    +
    +

    Customizing via CSS variables

    +

    + Override global, component, or utility class variables to customize Bootstrap just how you like. No need to + redeclare each rule, just a new variable value. +

    + +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/ComponentUtilities.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/ComponentUtilities.astro new file mode 100644 index 00000000..b54d4e40 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/ComponentUtilities.astro @@ -0,0 +1,158 @@ +--- +import { getVersionedDocsPath } from '@libs/path' +import Code from '@shortcodes/Code.astro' +--- + +
    +
    +
    + +
    + +
    + +
    +

    Components, meet the Utility API

    +

    + New in Bootstrap 5, our utilities are now generated by our Utility API. We built it as a feature-packed Sass map that can be quickly and easily customized. It's never been easier to + add, remove, or modify any utility classes. Make utilities responsive, add pseudo-class variants, and give them + custom names. +

    +
    +
    +
    +

    Quickly customize components

    +

    + Apply any of our included utility classes to our components to customize their appearance, like the navigation + example below. There are hundreds of classes available—from positioning and sizing to colors and effects. Mix them with CSS variable overrides for + even more control. +

    +
    + + +
    + + + + +`} + lang="html" + /> +

    + + Explore customized components + + +

    +
    +
    +

    Create and extend utilities

    +

    + Use Bootstrap's utility API to modify any of our included utilities or create your own custom utilities for any + project. Import Bootstrap first, then use Sass map functions to modify, add, or remove utilities. +

    + +

    + + Explore the utility API + + +

    +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Customize.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Customize.astro new file mode 100644 index 00000000..7422c517 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Customize.astro @@ -0,0 +1,69 @@ +--- +import { getVersionedDocsPath } from '@libs/path' +import Code from '@shortcodes/Code.astro' +--- + +
    +
    + +
    +

    Customize everything with Sass

    +

    + Bootstrap utilizes Sass for a modular and customizable architecture. Import only the components you need, enable + global options like gradients and shadows, and write your own CSS with our variables, maps, functions, and mixins. +

    +

    + + Learn more about customizing + + +

    +
    + +
    +
    +

    Include all of Bootstrap’s Sass

    +

    Import one stylesheet and you're off to the races with every feature of our CSS.

    + +

    Learn more about our global Sass options.

    +
    +
    +

    Include what you need

    +

    The easiest way to customize Bootstrap—include only the CSS you need.

    + +

    Learn more about using Bootstrap with Sass.

    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/GetStarted.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/GetStarted.astro new file mode 100644 index 00000000..4ad6807c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/GetStarted.astro @@ -0,0 +1,115 @@ +--- +import { getConfig } from '@libs/config' +import { getVersionedDocsPath } from '@libs/path' +import Code from '@shortcodes/Code.astro' +--- + +
    +
    + +
    +

    Get started any way you want

    +

    + Jump right into building with Bootstrap—use the CDN, install it via package manager, or download the source code. +

    +

    + + Read installation docs + + +

    +
    + +
    +
    + +

    Install via package manager

    +

    + Install Bootstrap’s source Sass and JavaScript files via npm, RubyGems, Composer, or Meteor. Package-managed + installs don’t include documentation or our full build scripts. You can also use any demo from our Examples repo to quickly jumpstart Bootstrap projects. +

    + + +

    + Read our installation docs for more info and additional + package managers. +

    +
    +
    + +

    Include via CDN

    +

    + When you only need to include Bootstrap’s compiled CSS or JS, you can use jsDelivr. See it in action with our simple quick start, or browse the examples to jumpstart your next project. You can also + choose to include Popper and our JS separately. +

    + `} + lang="html" + /> + `} + lang="html" + /> +
    + +
    +

    Read our getting started guides

    +

    Get a jump on including Bootstrap's source files in a new project with our official guides.

    + +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Icons.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Icons.astro new file mode 100644 index 00000000..4991dab5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Icons.astro @@ -0,0 +1,28 @@ +--- +import { getConfig } from '@libs/config' +import CircleSquareIcon from '@components/icons/CircleSquareIcon.astro' +import ResponsiveImage from '@layouts/partials/ResponsiveImage.astro' +--- + +
    +
    +
    + +
    +

    Personalize it with Bootstrap Icons

    +

    + Bootstrap Icons is an open source SVG icon library featuring over 1,800 glyphs, with + more added every release. They're designed to work in any project, whether you use Bootstrap itself or not. Use them + as SVGs or icon fonts—both options give you vector scaling and easy customization via CSS. +

    +

    + + Get Bootstrap Icons + + +

    +
    +
    + +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/MastHead.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/MastHead.astro new file mode 100644 index 00000000..f9054bac --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/MastHead.astro @@ -0,0 +1,60 @@ +--- +import { getConfig } from '@libs/config' +import { getVersionedDocsPath } from '@libs/path' +import Ads from '@components/Ads.astro' +import Code from '@components/shortcodes/Code.astro' +import ResponsiveImage from '@layouts/partials/ResponsiveImage.astro' +--- + +
    +
    +
    + + + Get Security Updates for Bootstrap 3 & 4 + + + + +

    Build fast, responsive sites with Bootstrap

    +

    + Powerful, extensible, and feature-packed frontend toolkit. Build and customize with Sass, utilize prebuilt grid + system and components, and bring projects to life with powerful JavaScript plugins. +

    + +

    + Currently v{getConfig().current_version} + · + Download + · + All releases +

    + +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Plugins.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Plugins.astro new file mode 100644 index 00000000..236ac5a1 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Plugins.astro @@ -0,0 +1,90 @@ +--- +import { getVersionedDocsPath } from '@libs/path' +import { getData } from '@libs/data' +import Code from '@shortcodes/Code.astro' + +const plugins = getData('plugins') +--- + +
    +
    +
    + +
    +

    Powerful JavaScript plugins without jQuery

    +

    + Add toggleable hidden elements, modals and offcanvas menus, popovers and tooltips, and so much more—all without + jQuery. Bootstrap's JavaScript is HTML-first, meaning most plugins are added with data attributes in your + HTML. Need more control? Include individual plugins programmatically. +

    +

    + + Learn more about Bootstrap JavaScript + + +

    +
    +
    +
    +

    Data attribute API

    +

    + Why write more JavaScript when you can write HTML? Nearly all of Bootstrap's JavaScript plugins feature a + first-class data API, allowing you to use JavaScript just by adding data attributes. +

    +
    + +
    + + + +
    `} + lang="html" + /> +

    + Learn more about our JavaScript as modules and using the programmatic API. +

    +
    +
    +

    Comprehensive set of plugins

    +

    + Bootstrap features a dozen plugins that you can drop into any project. Drop them in all at once, or choose just + the ones you need. +

    +
    +
    + { + plugins.map((plugin) => { + return ( + + ) + }) + } +
    +
    + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Themes.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Themes.astro new file mode 100644 index 00000000..68dd5e12 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/home/Themes.astro @@ -0,0 +1,35 @@ +--- +import { getConfig } from '@libs/config' +import DropletFillIcon from '@components/icons/DropletFillIcon.astro' +import ResponsiveImage from '@layouts/partials/ResponsiveImage.astro' +--- + +
    +
    +
    + +
    +

    Make it yours with official Bootstrap Themes

    +

    + Take Bootstrap to the next level with premium themes from the official Bootstrap Themes marketplace. Themes are built on Bootstrap as their own extended frameworks, rich with new components and plugins, + documentation, and powerful build tools. +

    +

    + + Browse Bootstrap Themes + + +

    +
    +
    + +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/BootstrapWhiteFillIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/BootstrapWhiteFillIcon.astro new file mode 100644 index 00000000..ef40e6a4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/BootstrapWhiteFillIcon.astro @@ -0,0 +1,18 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + + Bootstrap + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/CircleSquareIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/CircleSquareIcon.astro new file mode 100644 index 00000000..d7189506 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/CircleSquareIcon.astro @@ -0,0 +1,23 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/DropletFillIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/DropletFillIcon.astro new file mode 100644 index 00000000..d1fe5b51 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/DropletFillIcon.astro @@ -0,0 +1,24 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/GitHubIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/GitHubIcon.astro new file mode 100644 index 00000000..faa01434 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/GitHubIcon.astro @@ -0,0 +1,24 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + + GitHub + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/HamburgerIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/HamburgerIcon.astro new file mode 100644 index 00000000..8ff4730a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/HamburgerIcon.astro @@ -0,0 +1,23 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/OpenCollectiveIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/OpenCollectiveIcon.astro new file mode 100644 index 00000000..fc501641 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/OpenCollectiveIcon.astro @@ -0,0 +1,26 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + + Open Collective + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/Symbols.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/Symbols.astro new file mode 100644 index 00000000..44d3e731 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/Symbols.astro @@ -0,0 +1,148 @@ +--- +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/XIcon.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/XIcon.astro new file mode 100644 index 00000000..ea0f4bd8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/icons/XIcon.astro @@ -0,0 +1,23 @@ +--- +import type { SvgIconProps } from '@libs/icon' + +type Props = SvgIconProps + +const { class: className, height, width } = Astro.props +--- + + + X + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/AddedIn.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/AddedIn.astro new file mode 100644 index 00000000..d9a26ce5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/AddedIn.astro @@ -0,0 +1,16 @@ +--- +/* + * Outputs badge to identify the first version something was added + */ + +interface Props { + version: string +} + +const { version } = Astro.props +--- + +Added in v{version} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/BsTable.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/BsTable.astro new file mode 100644 index 00000000..df80455f --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/BsTable.astro @@ -0,0 +1,16 @@ +--- +interface Props { + /** + * The CSS class to apply to the table. + * Note that the prop is not used in this component, but in a rehype plugin applying the classes to the table element + * directly on the HTML AST (HAST) generated by Astro. + * @default "table" + * @see src/libs/rehype.ts + */ + class?: string +} +--- + +
    + +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Callout.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Callout.astro new file mode 100644 index 00000000..11243c84 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Callout.astro @@ -0,0 +1,44 @@ +--- +import { getCalloutByName } from '@libs/content' +import type { MarkdownInstance } from 'astro' + +interface Props { + /** + * The name of an existing callout to display located in `src/content/callouts`. + * This will override any content passed in via the default slot. + */ + name?: + | 'danger-async-methods' + | 'info-mediaqueries-breakpoints' + | 'info-npm-starter' + | 'info-prefersreducedmotion' + | 'info-sanitizer' + | 'warning-color-assistive-technologies' + | 'warning-data-bs-title-vs-title' + | 'warning-input-support' + /** + * The type of callout to display. One of `info`, `danger`, or `warning`. + * @default 'info' + */ + type?: 'danger' | 'info' | 'warning' +} + +const { name, type = 'info' } = Astro.props + +let Content: MarkdownInstance<{}>['Content'] | undefined + +if (name) { + const callout = await getCalloutByName(name) + + if (!callout) { + throw new Error(`Could not find callout with name '${name}'.`) + } + + const namedCallout = await callout.render() + Content = namedCallout.Content +} +--- + +
    + {Content ? : } +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/CalloutDeprecatedDarkVariants.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/CalloutDeprecatedDarkVariants.astro new file mode 100644 index 00000000..4033900d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/CalloutDeprecatedDarkVariants.astro @@ -0,0 +1,19 @@ +--- +/* + * Outputs message about dark mode component variants being deprecated in v5.3. + */ + +interface Props { + component: string +} + +const { component } = Astro.props +--- + +
    +

    + Heads up! Dark variants for components were deprecated in v5.3.0 with the introduction of color modes. + Instead of adding .{component}-dark, set data-bs-theme="dark" on the root element, a parent + wrapper, or the component itself. +

    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Code.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Code.astro new file mode 100644 index 00000000..231002a5 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Code.astro @@ -0,0 +1,156 @@ +--- +import fs from 'node:fs' +import path from 'node:path' +import { Prism } from '@astrojs/prism' + +interface Props { + /** + * The CSS class(es) to be added to the `pre` HTML element when rendering code blocks in Markdown. + * Note that this prop is not used when the component is invoked directly. + */ + class?: string + /** + * The code to highlight. + * If an array is passed, elements will be joined with a new line. + */ + code?: string | string[] + /** + * The CSS class(es) to be added to the `div` wrapper HTML element. + */ + containerClass?: string + /** + * The language to use for highlighting. + * @see https://prismjs.com/#supported-languages + */ + lang?: string + /** + * If the `filePath` prop is defined, this prop can be used to specify a regex containing a match group to extract + * only a part of the file. + */ + fileMatch?: string + /** + * A path to the file containing the code to highlight relative to the root of the repository. + * This takes precedence over the `code` prop. + */ + filePath?: string +} + +const { class: className, code, containerClass, fileMatch, filePath, lang } = Astro.props + +let codeToDisplay = filePath + ? fs.readFileSync(path.join(process.cwd(), filePath), 'utf8') + : Array.isArray(code) + ? code.join('\n') + : code + +if (filePath && fileMatch && codeToDisplay) { + const match = codeToDisplay.match(new RegExp(fileMatch)) + + if (!match || !match[0]) { + throw new Error(`The file at ${filePath} does not contains a match for the regex '${fileMatch}'.`) + } + + codeToDisplay = match[0] +} +--- + + + +
    + { + Astro.slots.has('pre') ? ( + + ) : ( +
    + +
    + ) + } +
    + { + codeToDisplay && lang ? ( + + ) : ( + /* prettier-ignore */
    + ) + } +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/DeprecatedIn.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/DeprecatedIn.astro new file mode 100644 index 00000000..50ba42b9 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/DeprecatedIn.astro @@ -0,0 +1,17 @@ +--- +/* + * Outputs badge to identify the version something was deprecated + */ + +interface Props { + version: string +} + +const { version } = Astro.props +--- + + + Deprecated in v{version} + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Example.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Example.astro new file mode 100644 index 00000000..a09fffeb --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Example.astro @@ -0,0 +1,105 @@ +--- +import { replacePlaceholdersInHtml } from '@libs/placeholder' +import { Prism } from '@astrojs/prism' + +interface Props { + /** + * Defines if extra JS snippet should be added to StackBlitz or not. + * @default false + */ + addStackblitzJs?: boolean + /** + * The example code. + * If an array is passed, elements will be joined with a new line. + */ + code: string | string[] + /** + * The CSS class(es) to be added to the preview wrapping `div` element. + */ + class?: string + /** + * The preview wrapping `div` element ID. + */ + id?: string + /** + * Language used to display the code. + * @default 'html' + */ + lang?: string + /** + * Defines if the markup should be visible or not. + * @default true + */ + showMarkup?: boolean + /** + * Defines if the preview should be visible or not. + * @default true + */ + showPreview?: boolean +} + +const { + addStackblitzJs = false, + code, + class: className, + id, + lang = 'html', + showMarkup = true, + showPreview = true +} = Astro.props + +let markup = Array.isArray(code) ? code.join('\n') : code +markup = replacePlaceholdersInHtml(markup) + +const simplifiedMarkup = markup + .replace( + //g, + (match, classes) => `...` + ) + .replace( + //g, + (match, classes) => `...` + ) +--- + +
    + { + showPreview && ( +
    + +
    + ) + } + + { + showMarkup && ( + <> + {showPreview && ( +
    + {lang} +
    + + +
    +
    + )} +
    + +
    + + ) + } +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/GuideFooter.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/GuideFooter.mdx new file mode 100644 index 00000000..426a71f2 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/GuideFooter.mdx @@ -0,0 +1,3 @@ +
    + +_See something wrong or out of date here? Please [open an issue on GitHub]([[config:repo]]/issues/new/choose). Need help troubleshooting? [Search or start a discussion]([[config:repo]]/discussions) on GitHub._ diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDataAttributes.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDataAttributes.mdx new file mode 100644 index 00000000..b7c6c0a7 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDataAttributes.mdx @@ -0,0 +1,5 @@ +As options can be passed via data attributes or JavaScript, you can append an option name to `data-bs-`, as in `data-bs-animation="{value}"`. Make sure to change the case type of the option name from “_camelCase_” to “_kebab-case_” when passing the options via data attributes. For example, use `data-bs-custom-class="beautifier"` instead of `data-bs-customClass="beautifier"`. + +As of Bootstrap 5.2.0, all components support an **experimental** reserved data attribute `data-bs-config` that can house simple component configuration as a JSON string. When an element has `data-bs-config='{"delay":0, "title":123}'` and `data-bs-title="456"` attributes, the final `title` value will be `456` and the separate data attributes will override values given on `data-bs-config`. In addition, existing data attributes are able to house JSON values like `data-bs-delay='{"show":0,"hide":150}'`. + +The final configuration object is the merged result of `data-bs-config`, `data-bs-`, and `js object` where the latest given key-value overrides the others. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDismiss.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDismiss.astro new file mode 100644 index 00000000..d1da8fc4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDismiss.astro @@ -0,0 +1,29 @@ +--- +import Code from '@shortcodes/Code.astro' + +interface Props { + name: string +} + +const { name } = Astro.props +--- + +

    + Dismissal can be achieved with the data-bs-dismiss attribute on a button within the {name} as demonstrated below: +

    + +`} + lang="html" +/> + +

    + or on a button outside the {name} using the additional data-bs-target as demonstrated below: +

    + +`} + lang="html" +/> diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDocs.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDocs.astro new file mode 100644 index 00000000..cf756af8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/JsDocs.astro @@ -0,0 +1,69 @@ +--- +import fs from 'node:fs' +import { getConfig } from '@libs/config' +import Code from '@shortcodes/Code.astro' + +// Prints everything between `// js-docs-start "name"` and `// js-docs-end "name"` +// comments in the docs. + +interface Props { + /** + * Reference name used to find the content to display within the content of the `file` prop. + */ + name: string + /** + * File path that contains the content to display relative to the root of the repository. + */ + file: string +} + +const { name, file } = Astro.props + +if (!name || !file) { + throw new Error( + `Missing required parameter(s) for the '' component, expected both 'name' and 'file' but got 'name: ${name}' and 'file: ${file}'.` + ) +} + +let content: string + +try { + const fileContent = fs.readFileSync(file, 'utf8') + + const matches = fileContent.match(new RegExp(`\/\/ js-docs-start ${name}\n((?:.|\n)*)\/\/ js-docs-end ${name}`, 'm')) + + if (!matches || !matches[1]) { + throw new Error( + `Failed to find the content named '${name}', make sure that '// js-docs-start ${name}' and '// js-docs-end ${name}' are defined.` + ) + } + + content = matches[1] + + // Fix the identation by removing extra spaces at the beginning of each line + const lines = content.split('\n') + const spaceCounts = lines.filter((line) => line.trim().length > 0).map((line) => line.match(/^ */)[0].length) + const minSpaces = spaceCounts.length ? Math.min(...spaceCounts) : 0 + content = lines.map((line) => line.slice(minSpaces)).join('\n') +} catch (error) { + throw new Error(`Failed to find the content to render in the '' component at '${file}'.`, { + cause: error + }) +} +--- + + +
    + + {file} + +
    + +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Placeholder.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Placeholder.astro new file mode 100644 index 00000000..3ebde32b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Placeholder.astro @@ -0,0 +1,27 @@ +--- +import { getPlaceholder, type PlaceholderOptions } from '@libs/placeholder' + +type Props = Partial + +const { + options: { background, color, showText, showTitle, text, title }, + props, + type +} = getPlaceholder(Astro.props) +--- + +{ + type === 'img' ? ( + + ) : ( + + {showTitle && {title}} + + {showText && ( + + {text} + + )} + + ) +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/ScssDocs.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/ScssDocs.astro new file mode 100644 index 00000000..6c267570 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/ScssDocs.astro @@ -0,0 +1,71 @@ +--- +import fs from 'node:fs' +import { getConfig } from '@libs/config' +import Code from '@shortcodes/Code.astro' + +// Prints everything between `// scss-docs-start "name"` and `// scss-docs-end "name"` +// comments in the docs. + +interface Props { + /** + * Reference name used to find the content to display within the content of the `file` prop. + */ + name: string + /** + * File path that contains the content to display relative to the root of the repository. + */ + file: string +} + +const { name, file } = Astro.props + +if (!name || !file) { + throw new Error( + `Missing required parameter(s) for the '' component, expected both 'name' and 'file' but got 'name: ${name}' and 'file: ${file}'.` + ) +} + +let content: string + +try { + const fileContent = fs.readFileSync(file, 'utf8') + + const matches = fileContent.match( + new RegExp(`\/\/ scss-docs-start ${name}\n((?:.|\n)*)\/\/ scss-docs-end ${name}`, 'm') + ) + + if (!matches || !matches[1]) { + throw new Error( + `Failed to find the content named '${name}', make sure that '// scss-docs-start ${name}' and '// scss-docs-end ${name}' are defined.` + ) + } + + content = matches[1].replaceAll(' !default', '') + + // Fix the identation by removing extra spaces at the beginning of each line + const lines = content.split('\n') + const spaceCounts = lines.filter((line) => line.trim().length > 0).map((line) => line.match(/^ */)[0].length) + const minSpaces = spaceCounts.length ? Math.min(...spaceCounts) : 0 + content = lines.map((line) => line.slice(minSpaces)).join('\n') +} catch (error) { + throw new Error(`Failed to find the content to render in the '' component at '${file}'.`, { + cause: error + }) +} +--- + + +
    + + {file} + +
    + +
    +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Table.astro b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Table.astro new file mode 100644 index 00000000..853b1970 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/Table.astro @@ -0,0 +1,31 @@ +--- +import Code from '@shortcodes/Code.astro' +import * as tableContent from '@shortcodes/TableContent.md' + +interface Props { + /** + * Any class(es) to be added to the `` element (both in the example and code snippet). + */ + class?: string + /** + * Show a simplified version in the example code snippet by replacing the table content inside `
    ` & `
    ` + * with `...`. + * @default true + */ + simplified?: boolean +} + +const { class: className, simplified = true } = Astro.props + +const tableCode = ` +${simplified ? ' ...' : await tableContent.compiledContent()} +` +--- + +
    + + +
    +
    + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/TableContent.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/TableContent.md new file mode 100644 index 00000000..cee54c6d --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/components/shortcodes/TableContent.md @@ -0,0 +1,28 @@ + + + # + First + Last + Handle + + + + + 1 + Mark + Otto + @mdo + + + 2 + Jacob + Thornton + @fat + + + 3 + John + Doe + @social + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/danger-async-methods.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/danger-async-methods.md new file mode 100644 index 00000000..7b7a654b --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/danger-async-methods.md @@ -0,0 +1 @@ +**All API methods are asynchronous and start a transition.** They return to the caller as soon as the transition is started, but before it ends. In addition, a method call on a transitioning component will be ignored. [Learn more in our JavaScript docs.](/docs/[[config:docs_version]]/getting-started/javascript/#asynchronous-functions-and-transitions) diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-mediaqueries-breakpoints.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-mediaqueries-breakpoints.md new file mode 100644 index 00000000..52be6738 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-mediaqueries-breakpoints.md @@ -0,0 +1 @@ +**Why subtract .02px?** Browsers don’t currently support [range context queries](https://www.w3.org/TR/mediaqueries-4/#range-context), so we work around the limitations of [`min-` and `max-` prefixes](https://www.w3.org/TR/mediaqueries-4/#mq-min-max) and viewports with fractional widths (which can occur under certain conditions on high-dpi devices, for instance) by using values with higher precision. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-npm-starter.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-npm-starter.md new file mode 100644 index 00000000..cc4a50e6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-npm-starter.md @@ -0,0 +1 @@ +**Get started with Bootstrap via npm with our starter project!** Head to the [Sass & JS example](https://github.com/twbs/examples/tree/main/sass-js) template repository to see how to build and customize Bootstrap in your own npm project. Includes Sass compiler, Autoprefixer, Stylelint, PurgeCSS, and Bootstrap Icons. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-prefersreducedmotion.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-prefersreducedmotion.md new file mode 100644 index 00000000..49d81ef8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-prefersreducedmotion.md @@ -0,0 +1 @@ +The animation effect of this component is dependent on the `prefers-reduced-motion` media query. See the [reduced motion section of our accessibility documentation](/docs/[[config:docs_version]]/getting-started/accessibility/#reduced-motion). diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-sanitizer.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-sanitizer.md new file mode 100644 index 00000000..516975b3 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/info-sanitizer.md @@ -0,0 +1 @@ +By default, this component uses the built-in content sanitizer, which strips out any HTML elements that are not explicitly allowed. See the [sanitizer section in our JavaScript documentation](/docs/[[config:docs_version]]/getting-started/javascript/#sanitizer) for more details. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-color-assistive-technologies.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-color-assistive-technologies.md new file mode 100644 index 00000000..8afa62ee --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-color-assistive-technologies.md @@ -0,0 +1 @@ +**Accessibility tip:** Using color to add meaning only provides a visual indication, which will not be conveyed to users of assistive technologies like screen readers. Please ensure the meaning is obvious from the content itself (e.g., the visible text with a [_sufficient_ color contrast](/docs/[[config:docs_version]]/getting-started/accessibility/#color-contrast)) or is included through alternative means, such as additional text hidden with the `.visually-hidden` class. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-data-bs-title-vs-title.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-data-bs-title-vs-title.md new file mode 100644 index 00000000..e932f22a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-data-bs-title-vs-title.md @@ -0,0 +1 @@ +Feel free to use either `title` or `data-bs-title` in your HTML. When `title` is used, Popper will replace it automatically with `data-bs-title` when the element is rendered. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-input-support.md b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-input-support.md new file mode 100644 index 00000000..f9d9c0ab --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/callouts/warning-input-support.md @@ -0,0 +1 @@ +Some date inputs types are [not fully supported](https://caniuse.com/input-datetime) by the latest versions of Safari and Firefox. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/config.ts b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/config.ts new file mode 100644 index 00000000..387a0052 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/config.ts @@ -0,0 +1,45 @@ +import { z, defineCollection } from 'astro:content' + +const docsSchema = z.object({ + added: z + .object({ + show_badge: z.boolean().optional(), + version: z.string() + }) + .optional(), + aliases: z.string().or(z.string().array()).optional(), + description: z.string(), + direction: z.literal('rtl').optional(), + extra_js: z + .object({ + async: z.boolean().optional(), + src: z.string() + }) + .array() + .optional(), + sections: z + .object({ + description: z.string(), + title: z.string() + }) + .array() + .optional(), + thumbnail: z.string().optional(), + title: z.string(), + toc: z.boolean().optional() +}) + +const docsCollection = defineCollection({ + schema: docsSchema +}) + +const calloutsSchema = z.object({}) + +const calloutsCollection = defineCollection({ + schema: calloutsSchema +}) + +export const collections = { + docs: docsCollection, + callouts: calloutsCollection +} diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/brand.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/brand.mdx new file mode 100644 index 00000000..0b171622 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/brand.mdx @@ -0,0 +1,41 @@ +--- +title: Brand guidelines +description: Documentation and examples for Bootstrap’s logo and brand usage guidelines. +toc: true +--- + +Have a need for Bootstrap’s brand resources? Great! We have only a few guidelines we follow, and in turn ask you to follow as well. + +## Logo + +When referencing Bootstrap, use our logo mark. Do not modify our logos in any way. Do not use Bootstrap’s branding for your own open or closed source projects. + +
    + Bootstrap +
    + +Our logo mark is also available in black and white. All rules for our primary logo apply to these as well. + +
    +
    + Bootstrap +
    +
    + Bootstrap +
    +
    + +## Name + +Bootstrap should always be referred to as just **Bootstrap**. No capital _s_. + +
    +
    +
    Bootstrap
    + Correct +
    +
    +
    BootStrap
    + Incorrect +
    +
    diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/license.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/license.mdx new file mode 100644 index 00000000..6479df67 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/license.mdx @@ -0,0 +1,32 @@ +--- +title: License FAQs +description: Commonly asked questions about Bootstrap’s open source license. +--- + +Bootstrap is released under the MIT license and is copyright {new Date().getFullYear()}. Boiled down to smaller chunks, it can be described with the following conditions. + +## It requires you to: + +- Keep the license and copyright notice included in Bootstrap’s CSS and JavaScript files when you use them in your works + +## It permits you to: + +- Freely download and use Bootstrap, in whole or in part, for personal, private, company internal, or commercial purposes +- Use Bootstrap in packages or distributions that you create +- Modify the source code +- Grant a sublicense to modify and distribute Bootstrap to third parties not included in the license + +## It forbids you to: + +- Hold the authors and license owners liable for damages as Bootstrap is provided without warranty +- Hold the creators or copyright holders of Bootstrap liable +- Redistribute any piece of Bootstrap without proper attribution +- Use any marks owned by Bootstrap in any way that might state or imply that Bootstrap endorses your distribution +- Use any marks owned by Bootstrap in any way that might state or imply that you created the Bootstrap software in question + +## It does not require you to: + +- Include the source of Bootstrap itself, or of any modifications you may have made to it, in any redistribution you may assemble that includes it +- Submit changes that you make to Bootstrap back to the Bootstrap project (though such feedback is encouraged) + +The full Bootstrap license is located [in the project repository]([[config:repo]]/blob/v[[config:current_version]]/LICENSE) for more information. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/overview.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/overview.mdx new file mode 100644 index 00000000..efd16c54 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/overview.mdx @@ -0,0 +1,27 @@ +--- +title: About Bootstrap +description: Learn more about the team maintaining Bootstrap, how and why the project started, and how to get involved. +aliases: + - "/about/" + - "/docs/[[config:docs_version]]/about/" +--- + +## Team + +Bootstrap is maintained by a [small team of developers](https://github.com/orgs/twbs/people) on GitHub. We’re actively looking to grow this team and would love to hear from you if you’re excited about CSS at scale, writing and maintaining vanilla JavaScript plugins, and improving build tooling processes for frontend code. + +## History + +Originally created by a designer and a developer at Twitter, Bootstrap has become one of the most popular front-end frameworks and open source projects in the world. + +Bootstrap was created at Twitter in mid-2010 by [@mdo](https://x.com/mdo) and [@fat](https://x.com/fat). Prior to being an open-sourced framework, Bootstrap was known as _Twitter Blueprint_. A few months into development, Twitter held its [first Hack Week](https://blog.x.com/engineering/en_us/a/2010/hack-week) and the project exploded as developers of all skill levels jumped in without any external guidance. It served as the style guide for internal tools development at the company for over a year before its public release, and continues to do so today. + +Originally [released](https://blog.x.com/developer/en_us/a/2011/bootstrap-twitter) on , we’ve since had over [twenty releases]([[config:repo]]/releases), including two major rewrites with v2 and v3. With Bootstrap 2, we added responsive functionality to the entire framework as an optional stylesheet. Building on that with Bootstrap 3, we rewrote the library once more to make it responsive by default with a mobile first approach. + +With Bootstrap 4, we once again rewrote the project to account for two key architectural changes: a migration to Sass and the move to CSS’s flexbox. Our intention is to help in a small way to move the web development community forward by pushing for newer CSS properties, fewer dependencies, and new technologies across more modern browsers. + +Our latest release, Bootstrap 5, focuses on improving v4’s codebase with as few major breaking changes as possible. We improved existing features and components, removed support for older browsers, dropped jQuery for regular JavaScript, and embraced more future-friendly technologies like CSS custom properties as part of our tooling. + +## Get involved + +Get involved with Bootstrap development by [opening an issue]([[config:repo]]/issues/new/choose) or submitting a pull request. Read our [contributing guidelines]([[config:repo]]/blob/v[[config:current_version]]/.github/CONTRIBUTING.md) for information on how we develop. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/team.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/team.mdx new file mode 100644 index 00000000..46b03d87 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/team.mdx @@ -0,0 +1,23 @@ +--- +title: Team +description: An overview of the founding team and core contributors to Bootstrap. +--- + +import { getData } from '@libs/data' + +Bootstrap is maintained by the founding team and a small group of invaluable core contributors, with the massive support and involvement of our community. + +
    + {getData('core-team').map((member) => { + return ( + + {`@${member.user}`} + + {member.name} @{member.user} + + + ) + })} +
    + +Get involved with Bootstrap development by [opening an issue]([[config:repo]]/issues/new/choose) or submitting a pull request. Read our [contributing guidelines]([[config:repo]]/blob/v[[config:current_version]]/.github/CONTRIBUTING.md) for information on how we develop. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/translations.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/translations.mdx new file mode 100644 index 00000000..7db4ab84 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/about/translations.mdx @@ -0,0 +1,20 @@ +--- +title: Translations +description: Links to community-translated Bootstrap documentation sites. +--- + +import { getData } from '@libs/data' + +Community members have translated Bootstrap’s documentation into various languages. None are officially supported and they may not always be up-to-date. + + + +**We don’t help organize or host translations, we just link to them.** + +Finished a new or better translation? Open a pull request to add it to our list. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/accordion.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/accordion.mdx new file mode 100644 index 00000000..06c95d4a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/accordion.mdx @@ -0,0 +1,240 @@ +--- +title: Accordion +description: Build vertically collapsing accordions in combination with our Collapse JavaScript plugin. +aliases: + - "/components/" + - "/docs/[[config:docs_version]]/components/" +toc: true +--- + +## How it works + +The accordion uses [collapse]([[docsref:/components/collapse]]) internally to make it collapsible. + + + +## Example + +Click the accordions below to expand/collapse the accordion content. + +To render an accordion that’s expanded by default: +- add the `.show` class on the `.accordion-collapse` element. +- drop the `.collapsed` class from the `.accordion-button` element and set its `aria-expanded` attribute to `true`. + + +
    +

    + +

    +
    +
    + This is the first item’s accordion body. It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It’s also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    +

    + +

    +
    +
    + This is the second item’s accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It’s also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    +

    + +

    +
    +
    + This is the third item’s accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It’s also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    + `} /> + +### Flush + +Add `.accordion-flush` to remove some borders and rounded corners to render accordions edge-to-edge with their parent container. + + +
    +

    + +

    +
    +
    Placeholder content for this accordion, which is intended to demonstrate the .accordion-flush class. This is the first item’s accordion body.
    +
    +
    +
    +

    + +

    +
    +
    Placeholder content for this accordion, which is intended to demonstrate the .accordion-flush class. This is the second item’s accordion body. Let’s imagine this being filled with some actual content.
    +
    +
    +
    +

    + +

    +
    +
    Placeholder content for this accordion, which is intended to demonstrate the .accordion-flush class. This is the third item’s accordion body. Nothing more exciting happening here in terms of content, but just filling up the space to make it look, at least at first glance, a bit more representative of how this would look in a real-world application.
    +
    +
    + `} /> + +### Always open + +Omit the `data-bs-parent` attribute on each `.accordion-collapse` to make accordion items stay open when another item is opened. + + +
    +

    + +

    +
    +
    + This is the first item’s accordion body. It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It’s also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    +

    + +

    +
    +
    + This is the second item’s accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It’s also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    +
    +

    + +

    +
    +
    + This is the third item’s accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It’s also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow. +
    +
    +
    + `} /> + +## Accessibility + +Please read the [collapse accessibility section]([[docsref:/components/collapse#accessibility]]) for more information. + +## CSS + +### Variables + + + +As part of Bootstrap’s evolving CSS variables approach, accordions now use local CSS variables on `.accordion` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. + + + +### Sass variables + + + +## Usage + +The collapse plugin utilizes a few classes to handle the heavy lifting: + +- `.collapse` hides the content +- `.collapse.show` shows the content +- `.collapsing` is added when the transition starts, and removed when it finishes + +These classes can be found in `_transitions.scss`. + +### Via data attributes + +Just add `data-bs-toggle="collapse"` and a `data-bs-target` to the element to automatically assign control of one or more collapsible elements. The `data-bs-target` attribute accepts a CSS selector to apply the collapse to. Be sure to add the class `collapse` to the collapsible element. If you’d like it to default open, add the additional class `show`. + +To add accordion group management to a collapsible area, add the data attribute `data-bs-parent="#selector"`. + +### Via JavaScript + +Enable manually with: + +```js +const accordionCollapseElementList = document.querySelectorAll('#myAccordion.collapse') +const accordionCollapseList = [...accordionCollapseElementList].map(accordionCollapseEl => new bootstrap.Collapse(accordionCollapseEl)) +``` + +### Options + + + + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +`parent` | selector, DOM element | `null` | If parent is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the `card` class). The attribute has to be set on the target collapsible area. | +`toggle` | boolean | `true` | Toggles the collapsible element on invocation. | + + +### Methods + + + +Activates your content as a collapsible element. Accepts an optional options `object`. + +You can create a collapse instance with the constructor, for example: + +```js +const bsCollapse = new bootstrap.Collapse('#myCollapse', { + toggle: false +}) +``` + + +| Method | Description | +| --- | --- | +| `dispose` | Destroys an element’s collapse. (Removes stored data on the DOM element) | +| `getInstance` | Static method which allows you to get the collapse instance associated to a DOM element, you can use it like this: `bootstrap.Collapse.getInstance(element)`. | +| `getOrCreateInstance` | Static method which returns a collapse instance associated to a DOM element or create a new one in case it wasn’t initialized. You can use it like this: `bootstrap.Collapse.getOrCreateInstance(element)`. | +| `hide` | Hides a collapsible element. **Returns to the caller before the collapsible element has actually been hidden** (e.g., before the `hidden.bs.collapse` event occurs). | +| `show` | Shows a collapsible element. **Returns to the caller before the collapsible element has actually been shown** (e.g., before the `shown.bs.collapse` event occurs). | +| `toggle` | Toggles a collapsible element to shown or hidden. **Returns to the caller before the collapsible element has actually been shown or hidden** (i.e. before the `shown.bs.collapse` or `hidden.bs.collapse` event occurs). | + + +### Events + +Bootstrap’s collapse class exposes a few events for hooking into collapse functionality. + + +| Event type | Description | +| --- | --- | +| `hide.bs.collapse` | This event is fired immediately when the `hide` method has been called. | +| `hidden.bs.collapse` | This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete). | +| `show.bs.collapse` | This event fires immediately when the `show` instance method is called. | +| `shown.bs.collapse` | This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete). | + + +```js +const myCollapsible = document.getElementById('myCollapsible') +myCollapsible.addEventListener('hidden.bs.collapse', event => { + // do something... +}) +``` diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/alerts.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/alerts.mdx new file mode 100644 index 00000000..e2560446 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/alerts.mdx @@ -0,0 +1,218 @@ +--- +title: Alerts +description: Provide contextual feedback messages for typical user actions with the handful of available and flexible alert messages. +toc: true +--- + +import { getData } from '@libs/data' + +## Examples + +Alerts are available for any length of text, as well as an optional close button. For proper styling, use one of the eight **required** contextual classes (e.g., `.alert-success`). For inline dismissal, use the [alerts JavaScript plugin](#dismissing). + + +**Heads up!** As of v5.3.0, the `alert-variant()` Sass mixin is deprecated. Alert variants now have their CSS variables overridden in [a Sass loop](#sass-loops). + + + ``)} /> + + + +### Live example + +Click the button below to show an alert (hidden with inline styles to start), then dismiss (and destroy) it with the built-in close button. + + +`} /> + +We use the following JavaScript to trigger our live alert demo: + + + +### Link color + +Use the `.alert-link` utility class to quickly provide matching colored links within any alert. + + ``)} /> + +### Additional content + +Alerts can also contain additional HTML elements like headings, paragraphs and dividers. + + +

    Well done!

    +

    Aww yeah, you successfully read this important alert message. This example text is going to run a bit longer so that you can see how spacing within an alert works with this kind of content.

    +
    +

    Whenever you need to, be sure to use margin utilities to keep things nice and tidy.

    + `} /> + +### Icons + +Similarly, you can use [flexbox utilities]([[docsref:/utilities/flex]]) and [Bootstrap Icons]([[config:icons]]) to create alerts with icons. Depending on your icons and content, you may want to add more utilities or custom styles. + + + + + +
    + An example alert with an icon +
    + `} /> + +Need more than one icon for your alerts? Consider using more Bootstrap Icons and making a local SVG sprite like so to easily reference the same icons repeatedly. + + + + + + + + + + + + + + + + + `} /> + +### Dismissing + +Using the alert JavaScript plugin, it’s possible to dismiss any alert inline. Here’s how: + +- Be sure you’ve loaded the alert plugin, or the compiled Bootstrap JavaScript. +- Add a [close button]([[docsref:/components/close-button]]) and the `.alert-dismissible` class, which adds extra padding to the right of the alert and positions the close button. +- On the close button, add the `data-bs-dismiss="alert"` attribute, which triggers the JavaScript functionality. Be sure to use the ` + `} /> + + +When an alert is dismissed, the element is completely removed from the page structure. If a keyboard user dismisses the alert using the close button, their focus will suddenly be lost and, depending on the browser, reset to the start of the page/document. For this reason, we recommend including additional JavaScript that listens for the `closed.bs.alert` event and programmatically sets `focus()` to the most appropriate location in the page. If you’re planning to move focus to a non-interactive element that normally does not receive focus, make sure to add `tabindex="-1"` to the element. + + +## CSS + +### Variables + + + +As part of Bootstrap’s evolving CSS variables approach, alerts now use local CSS variables on `.alert` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. + + + +### Sass variables + + + +### Sass mixins + + + + + +### Sass loops + +Loop that generates the modifier classes with an overriding of CSS variables. + + + +## JavaScript behavior + +### Initialize + +Initialize elements as alerts + +```js +const alertList = document.querySelectorAll('.alert') +const alerts = [...alertList].map(element => new bootstrap.Alert(element)) +``` + + +For the sole purpose of dismissing an alert, it isn’t necessary to initialize the component manually via the JS API. By making use of `data-bs-dismiss="alert"`, the component will be initialized automatically and properly dismissed. + +See the [triggers](#triggers) section for more details. + + +### Triggers + + + +**Note that closing an alert will remove it from the DOM.** + +### Methods + +You can create an alert instance with the alert constructor, for example: + +```js +const bsAlert = new bootstrap.Alert('#myAlert') +``` + +This makes an alert listen for click events on descendant elements which have the `data-bs-dismiss="alert"` attribute. (Not necessary when using the data-api’s auto-initialization.) + + +| Method | Description | +| --- | --- | +| `close` | Closes an alert by removing it from the DOM. If the `.fade` and `.show` classes are present on the element, the alert will fade out before it is removed. | +| `dispose` | Destroys an element’s alert. (Removes stored data on the DOM element) | +| `getInstance` | Static method which allows you to get the alert instance associated to a DOM element. For example: `bootstrap.Alert.getInstance(alert)`. | +| `getOrCreateInstance` | Static method which returns an alert instance associated to a DOM element or create a new one in case it wasn’t initialized. You can use it like this: `bootstrap.Alert.getOrCreateInstance(element)`. | + + +Basic usage: + +```js +const alert = bootstrap.Alert.getOrCreateInstance('#myAlert') +alert.close() +``` + +### Events + +Bootstrap’s alert plugin exposes a few events for hooking into alert functionality. + + +| Event | Description | +| --- | --- | +| `close.bs.alert` | Fires immediately when the `close` instance method is called. | +| `closed.bs.alert` | Fired when the alert has been closed and CSS transitions have completed. | + + +```js +const myAlert = document.getElementById('myAlert') +myAlert.addEventListener('closed.bs.alert', event => { + // do something, for instance, explicitly move focus to the most appropriate element, + // so it doesn’t get lost/reset to the start of the page + // document.getElementById('...').focus() +}) +``` diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/badge.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/badge.mdx new file mode 100644 index 00000000..b3e574b6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/badge.mdx @@ -0,0 +1,83 @@ +--- +title: Badges +description: Documentation and examples for badges, our small count and labeling component. +toc: true +--- + +import { getData } from '@libs/data' + +## Examples + +Badges scale to match the size of the immediate parent element by using relative font sizing and `em` units. As of v5, badges no longer have focus or hover styles for links. + +### Headings + +Example heading New +

    Example heading New

    +

    Example heading New

    +

    Example heading New

    +
    Example heading New
    +
    Example heading New
    `} /> + +### Buttons + +Badges can be used as part of links or buttons to provide a counter. + + + Notifications 4 + `} /> + +Note that depending on how they are used, badges may be confusing for users of screen readers and similar assistive technologies. While the styling of badges provides a visual cue as to their purpose, these users will simply be presented with the content of the badge. Depending on the specific situation, these badges may seem like random additional words or numbers at the end of a sentence, link, or button. + +Unless the context is clear (as with the “Notifications” example, where it is understood that the “4” is the number of notifications), consider including additional context with a visually hidden piece of additional text. + +### Positioned + +Use utilities to modify a `.badge` and position it in the corner of a link or button. + + + Inbox + + 99+ + unread messages + + `} /> + +You can also replace the `.badge` class with a few more utilities without a count for a more generic indicator. + + + Profile + + New alerts + + `} /> + +## Background colors + + + +Set a `background-color` with contrasting foreground `color` with [our `.text-bg-{color}` helpers]([[docsref:helpers/color-background]]). Previously it was required to manually pair your choice of [`.text-{color}`]([[docsref:/utilities/colors]]) and [`.bg-{color}`]([[docsref:/utilities/background]]) utilities for styling, which you still may use if you prefer. + + `${themeColor.title}`)} /> + + + +## Pill badges + +Use the `.rounded-pill` utility class to make badges more rounded with a larger `border-radius`. + + `${themeColor.title}`)} /> + +## CSS + +### Variables + + + +As part of Bootstrap’s evolving CSS variables approach, badges now use local CSS variables on `.badge` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. + + + +### Sass variables + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/breadcrumb.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/breadcrumb.mdx new file mode 100644 index 00000000..50cceb1c --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/breadcrumb.mdx @@ -0,0 +1,98 @@ +--- +title: Breadcrumb +description: Indicate the current page’s location within a navigational hierarchy that automatically adds separators via CSS. +toc: true +--- + +## Example + +Use an ordered or unordered list with linked list items to create a minimally styled breadcrumb. Use our utilities to add additional styles as desired. + + + + + + + + `} /> + +## Dividers + +Dividers are automatically added in CSS through [`::before`](https://developer.mozilla.org/en-US/docs/Web/CSS/::before) and [`content`](https://developer.mozilla.org/en-US/docs/Web/CSS/content). They can be changed by modifying a local CSS custom property `--bs-breadcrumb-divider`, or through the `$breadcrumb-divider` Sass variable — and `$breadcrumb-divider-flipped` for its RTL counterpart, if needed. We default to our Sass variable, which is set as a fallback to the custom property. This way, you get a global divider that you can override without recompiling CSS at any time. + + + + `} /> + +When modifying via Sass, the [quote](https://sass-lang.com/documentation/modules/string/#quote) function is required to generate the quotes around a string. For example, using `>` as the divider, you can use this: + +```scss +$breadcrumb-divider: quote(">"); +``` + +It’s also possible to use an **embedded SVG icon**. Apply it via our CSS custom property, or use the Sass variable. + + +**Inlined SVG requires properly escaped characters.** Some reserved characters, such as `<`, `>` and `#`, must be URL-encoded or escaped. We do this with the `$breadcrumb-divider` variable using our [`escape-svg()` Sass function]([[docsref:/customize/sass#escape-svg]]). When customizing the CSS variable, you must handle this yourself. Read [Kevin Weber’s explanations on CodePen](https://codepen.io/kevinweber/pen/dXWoRw ) for more info. + + + + + `} /> + +```scss +$breadcrumb-divider: url("data:image/svg+xml,"); +``` + +You can also remove the divider setting `--bs-breadcrumb-divider: '';` (empty strings in CSS custom properties counts as a value), or setting the Sass variable to `$breadcrumb-divider: none;`. + + + + `} /> + + +```scss +$breadcrumb-divider: none; +``` + +## Accessibility + +Since breadcrumbs provide a navigation, it’s a good idea to add a meaningful label such as `aria-label="breadcrumb"` to describe the type of navigation provided in the ``} /> + +## Directions + + +**Directions are flipped in RTL mode.** As such, `.dropstart` will appear on the right side. + + +### Centered + +Make the dropdown menu centered below the toggle with `.dropdown-center` on the parent element. + + + + + `} /> + +### Dropup + +Trigger dropdown menus above elements by adding `.dropup` to the parent element. + + + + + +
    + + + +
    `} /> + +```html + +
    + + +
    + + +
    + + + +
    +``` + +### Dropup centered + +Make the dropup menu centered above the toggle with `.dropup-center` on the parent element. + + + + + `} /> + +### Dropend + +Trigger dropdown menus at the right of the elements by adding `.dropend` to the parent element. + + + + + +
    + + + +
    `} /> + +```html + +
    + + +
    + + +
    + + + +
    +``` + +### Dropstart + +Trigger dropdown menus at the left of the elements by adding `.dropstart` to the parent element. + + + + + +
    + + + +
    `} /> + +```html + +
    + + +
    + + +
    + + + +
    +``` + +## Menu items + +You can use `` or ` + + `} /> + +You can also create non-interactive dropdown items with `.dropdown-item-text`. Feel free to style further with custom CSS or text utilities. + + +
  • Dropdown item text
  • +
  • Action
  • +
  • Another action
  • +
  • Something else here
  • + `} /> + +### Active + +Add `.active` to items in the dropdown to **style them as active**. To convey the active state to assistive technologies, use the `aria-current` attribute — using the `page` value for the current page, or `true` for the current item in a set. + + +
  • Regular link
  • +
  • Active link
  • +
  • Another link
  • + `} /> + +### Disabled + +Add `.disabled` to items in the dropdown to **style them as disabled**. + + +
  • Regular link
  • +
  • Disabled link
  • +
  • Another link
  • + `} /> + +## Menu alignment + +By default, a dropdown menu is automatically positioned 100% from the top and along the left side of its parent. You can change this with the directional `.drop*` classes, but you can also control them with additional modifier classes. + +Add `.dropdown-menu-end` to a `.dropdown-menu` to right align the dropdown menu. Directions are mirrored when using Bootstrap in RTL, meaning `.dropdown-menu-end` will appear on the left side. + + +**Heads up!** Dropdowns are positioned thanks to Popper except when they are contained in a navbar. + + + + + + `} /> + +### Responsive alignment + +If you want to use responsive alignment, disable dynamic positioning by adding the `data-bs-display="static"` attribute and use the responsive variation classes. + +To align **right** the dropdown menu with the given breakpoint or larger, add `.dropdown-menu{-sm|-md|-lg|-xl|-xxl}-end`. + + + + + `} /> + +To align **left** the dropdown menu with the given breakpoint or larger, add `.dropdown-menu-end` and `.dropdown-menu{-sm|-md|-lg|-xl|-xxl}-start`. + + + + + `} /> + +Note that you don’t need to add a `data-bs-display="static"` attribute to dropdown buttons in navbars, since Popper isn’t used in navbars. + +### Alignment options + +Taking most of the options shown above, here’s a small kitchen sink demo of various dropdown alignment options in one place. + + + + + + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    `} /> + +## Menu content + +### Headers + +Add a header to label sections of actions in any dropdown menu. + + +
  • +
  • Action
  • +
  • Another action
  • + `} /> + +### Dividers + +Separate groups of related menu items with a divider. + + +
  • Action
  • +
  • Another action
  • +
  • Something else here
  • +
  • +
  • Separated link
  • + `} /> + +### Text + +Place any freeform text within a dropdown menu with text and use [spacing utilities]([[docsref:/utilities/spacing]]). Note that you’ll likely need additional sizing styles to constrain the menu width. + + +

    + Some example text that’s free-flowing within the dropdown menu. +

    +

    + And this is more example text. +

    + `} /> + +### Forms + +Put a form within a dropdown menu, or make it into a dropdown menu, and use [margin or padding utilities]([[docsref:/utilities/spacing]]) to give it the negative space you require. + + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + +
    + + New around here? Sign up + Forgot password? + `} /> + + + + + `} /> + +## Dropdown options + +Use `data-bs-offset` or `data-bs-reference` to change the location of the dropdown. + + + +
    + + + +
    + `} /> + +### Auto close behavior + +By default, the dropdown menu is closed when clicking inside or outside the dropdown menu. You can use the `autoClose` option to change this behavior of the dropdown. + + + + + + +
    + + +
    + +
    + + +
    + +
    + + +
    `} /> + +## CSS + +### Variables + + + +As part of Bootstrap’s evolving CSS variables approach, dropdowns now use local CSS variables on `.dropdown-menu` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. + + + + +Dropdown items include at least one variable that is not set on `.dropdown`. This allows you to provide a new value while Bootstrap defaults to a fallback value. + +- `--bs-dropdown-item-border-radius` + + +Customization through CSS variables can be seen on the `.dropdown-menu-dark` class where we override specific values without adding duplicate CSS selectors. + + + +### Sass variables + +Variables for all dropdowns: + + + +Variables for the [dark dropdown](#dark-dropdowns): + + + +Variables for the CSS-based carets that indicate a dropdown’s interactivity: + + + +### Sass mixins + +Mixins are used to generate the CSS-based carets and can be found in `scss/mixins/_caret.scss`. + + + +## Usage + +Via data attributes or JavaScript, the dropdown plugin toggles hidden content (dropdown menus) by toggling the `.show` class on the parent `.dropdown-menu`. The `data-bs-toggle="dropdown"` attribute is relied on for closing dropdown menus at an application level, so it’s a good idea to always use it. + + +On touch-enabled devices, opening a dropdown adds empty `mouseover` handlers to the immediate children of the `` element. This admittedly ugly hack is necessary to work around a [quirk in iOs’ event delegation](https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html), which would otherwise prevent a tap anywhere outside of the dropdown from triggering the code that closes the dropdown. Once the dropdown is closed, these additional empty `mouseover` handlers are removed. + + +### Via data attributes + +Add `data-bs-toggle="dropdown"` to a link or button to toggle a dropdown. + +```html + +``` + +### Via JavaScript + + +Dropdowns must have `data-bs-toggle="dropdown"` on their trigger element, regardless of whether you call your dropdown via JavaScript or use the data-api. + + +Call the dropdowns via JavaScript: + +```js +const dropdownElementList = document.querySelectorAll('.dropdown-toggle') +const dropdownList = [...dropdownElementList].map(dropdownToggleEl => new bootstrap.Dropdown(dropdownToggleEl)) +``` + +### Options + + + + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `autoClose` | boolean, string | `true` | Configure the auto close behavior of the dropdown:
    • `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.
    • `false` - the dropdown will be closed by clicking the toggle button and manually calling `hide` or `toggle` method. (Also will not be closed by pressing Esc key)
    • `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.
    • `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
    Note: the dropdown can always be closed with the Esc key. | +| `boundary` | string, element | `'clippingParents'` | Overflow constraint boundary of the dropdown menu (applies only to Popper’s preventOverflow modifier). By default it’s `clippingParents` and can accept an HTMLElement reference (via JavaScript only). For more information refer to Popper’s [detectOverflow docs](https://popper.js.org/docs/v2/utils/detect-overflow/#boundary). | +| `display` | string | `'dynamic'` | By default, we use Popper for dynamic positioning. Disable this with `static`. | +| `offset` | array, string, function | `[0, 2]` | Offset of the dropdown relative to its target. You can pass a string in data attributes with comma separated values like: `data-bs-offset="10,20"`. When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: [skidding](https://popper.js.org/docs/v2/modifiers/offset/#skidding-1), [distance](https://popper.js.org/docs/v2/modifiers/offset/#distance-1). For more information refer to Popper’s [offset docs](https://popper.js.org/docs/v2/modifiers/offset/#options). | +| `popperConfig` | null, object, function | `null` | To change Bootstrap’s default Popper config, see [Popper’s configuration](https://popper.js.org/docs/v2/constructors/#options). When a function is used to create the Popper configuration, it’s called with an object that contains the Bootstrap’s default Popper configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Popper. | +| `reference` | string, element, object | `'toggle'` | Reference element of the dropdown menu. Accepts the values of `'toggle'`, `'parent'`, an HTMLElement reference or an object providing `getBoundingClientRect`. For more information refer to Popper’s [constructor docs](https://popper.js.org/docs/v2/constructors/#createpopper) and [virtual element docs](https://popper.js.org/docs/v2/virtual-elements/). | +
    + +#### Using function with `popperConfig` + +```js +const dropdown = new bootstrap.Dropdown(element, { + popperConfig(defaultBsPopperConfig) { + // const newPopperConfig = {...} + // use defaultBsPopperConfig if needed... + // return newPopperConfig + } +}) +``` + +### Methods + + +| Method | Description | +| --- | --- | +| `dispose` | Destroys an element’s dropdown. (Removes stored data on the DOM element) | +| `getInstance` | Static method which allows you to get the dropdown instance associated to a DOM element, you can use it like this: `bootstrap.Dropdown.getInstance(element)`. | +| `getOrCreateInstance` | Static method which returns a dropdown instance associated to a DOM element or create a new one in case it wasn’t initialized. You can use it like this: `bootstrap.Dropdown.getOrCreateInstance(element)`. | +| `hide` | Hides the dropdown menu of a given navbar or tabbed navigation. | +| `show` | Shows the dropdown menu of a given navbar or tabbed navigation. | +| `toggle` | Toggles the dropdown menu of a given navbar or tabbed navigation. | +| `update` | Updates the position of an element’s dropdown. | + + +### Events + +All dropdown events are fired at the toggling element and then bubbled up. So you can also add event listeners on the `.dropdown-menu`’s parent element. `hide.bs.dropdown` and `hidden.bs.dropdown` events have a `clickEvent` property (only when the original Event type is `click`) that contains an Event Object for the click event. + + +| Event type | Description | +| --- | --- | +| `hide.bs.dropdown` | Fires immediately when the `hide` instance method has been called. | +| `hidden.bs.dropdown` | Fired when the dropdown has finished being hidden from the user and CSS transitions have completed. | +| `show.bs.dropdown` | Fires immediately when the `show` instance method is called. | +| `shown.bs.dropdown` | Fired when the dropdown has been made visible to the user and CSS transitions have completed. | + + +```js +const myDropdown = document.getElementById('myDropdown') +myDropdown.addEventListener('show.bs.dropdown', event => { + // do something... +}) +``` diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/list-group.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/list-group.mdx new file mode 100644 index 00000000..59827ddd --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/components/list-group.mdx @@ -0,0 +1,448 @@ +--- +title: List group +description: List groups are a flexible and powerful component for displaying a series of content. Modify and extend them to support just about any content within. +toc: true +--- + +import { getData } from '@libs/data' + +## Basic example + +The most basic list group is an unordered list with list items and the proper classes. Build upon it with the options that follow, or with your own CSS as needed. + + +
  • An item
  • +
  • A second item
  • +
  • A third item
  • +
  • A fourth item
  • +
  • And a fifth one
  • + `} /> + +## Active items + +Add `.active` to a `.list-group-item` to indicate the current active selection. + + +
  • An active item
  • +
  • A second item
  • +
  • A third item
  • +
  • A fourth item
  • +
  • And a fifth one
  • + `} /> + +## Links and buttons + +Use ``s or ` + + + + + `} /> + +## Flush + +Add `.list-group-flush` to remove some borders and rounded corners to render list group items edge-to-edge in a parent container (e.g., cards). + + +
  • An item
  • +
  • A second item
  • +
  • A third item
  • +
  • A fourth item
  • +
  • And a fifth one
  • + `} /> + +## Numbered + +Add the `.list-group-numbered` modifier class (and optionally use an `
      ` element) to opt into numbered list group items. Numbers are generated via CSS (as opposed to a `
        `s default browser styling) for better placement inside list group items and to allow for better customization. + +Numbers are generated by `counter-reset` on the `
          `, and then styled and placed with a `::before` pseudo-element on the `
        1. ` with `counter-increment` and `content`. + + +
        2. A list item
        3. +
        4. A list item
        5. +
        6. A list item
        7. +
        `} /> + +These work great with custom content as well. + + +
      1. +
        +
        Subheading
        + Content for list item +
        + 14 +
      2. +
      3. +
        +
        Subheading
        + Content for list item +
        + 14 +
      4. +
      5. +
        +
        Subheading
        + Content for list item +
        + 14 +
      6. +
      `} /> + +## Horizontal + +Add `.list-group-horizontal` to change the layout of list group items from vertical to horizontal across all breakpoints. Alternatively, choose a responsive variant `.list-group-horizontal-{sm|md|lg|xl|xxl}` to make a list group horizontal starting at that breakpoint’s `min-width`. Currently **horizontal list groups cannot be combined with flush list groups.** + +**ProTip:** Want equal-width list group items when horizontal? Add `.flex-fill` to each list group item. + + `
        +
      • An item
      • +
      • A second item
      • +
      • A third item
      • +
      `)} /> + +## Variants + + +**Heads up!** As of v5.3.0, the `list-group-item-variant()` Sass mixin is deprecated. List group item variants now have their CSS variables overridden in [a Sass loop](#sass-loops). + + +Use contextual classes to style list items with a stateful background and color. + + +
    1. A simple default list group item
    2. + `, + ...getData('theme-colors').map((themeColor) => `
    3. A simple ${themeColor.name} list group item
    4. `), + `` + ]} /> + +### For links and buttons + +Contextual classes also work with `.list-group-item-action` for `
      ` and ` + + + + + + + + +```html + +``` + + +In the above static example, we use `
      `, to avoid issues with the heading hierarchy in the documentation page. Structurally, however, a modal dialog represents its own separate document/context, so the `.modal-title` should ideally be an `

      `. If necessary, you can use the [font size utilities]([[docsref:/utilities/text#font-size]]) to control the heading’s appearance. All the following live examples use this approach. + + +### Live demo + +Toggle a working modal demo by clicking the button below. It will slide down and fade in from the top of the page. + + + +
      + +
      + +```html + + + + + +``` + +### Static backdrop + +When backdrop is set to static, the modal will not close when clicking outside of it. Click the button below to try it. + + + +
      + +
      + +```html + + + + + +``` + +### Scrolling long content + +When modals become too long for the user’s viewport or device, they scroll independent of the page itself. Try the demo below to see what we mean. + + + +
      + +
      + +You can also create a scrollable modal that allows scrolling the modal body by adding `.modal-dialog-scrollable` to `.modal-dialog`. + + + +
      + +
      + +```html + + +``` + +### Vertically centered + +Add `.modal-dialog-centered` to `.modal-dialog` to vertically center the modal. + +

      `} /> + +## Display headings + +Traditional heading elements are designed to work best in the meat of your page content. When you need a heading to stand out, consider using a **display heading**—a larger, slightly more opinionated heading style. + +
      +
      Display 1
      +
      Display 2
      +
      Display 3
      +
      Display 4
      +
      Display 5
      +
      Display 6
      +
      + +```html +

      Display 1

      +

      Display 2

      +

      Display 3

      +

      Display 4

      +

      Display 5

      +

      Display 6

      +``` + +Display headings are configured via the `$display-font-sizes` Sass map and two variables, `$display-font-weight` and `$display-line-height`. + +Display headings are customizable via two variables, `$display-font-family` and `$display-font-style`. + + + +## Lead + +Make a paragraph stand out by adding `.lead`. + + + This is a lead paragraph. It stands out from regular paragraphs. +

      `} /> + +## Inline text elements + +Styling for common inline HTML5 elements. + +You can use the mark tag to highlight text.

      +

      This line of text is meant to be treated as deleted text.

      +

      This line of text is meant to be treated as no longer accurate.

      +

      This line of text is meant to be treated as an addition to the document.

      +

      This line of text will render as underlined.

      +

      This line of text is meant to be treated as fine print.

      +

      This line rendered as bold text.

      +

      This line rendered as italicized text.

      `} /> + +Beware that those tags should be used for semantic purpose: + +- `` represents text which is marked or highlighted for reference or notation purposes. +- `` represents side-comments and small print, like copyright and legal text. +- `` represents element that are no longer relevant or no longer accurate. +- `` represents a span of inline text which should be rendered in a way that indicates that it has a non-textual annotation. + +If you want to style your text, you should use the following classes instead: + +- `.mark` will apply the same styles as ``. +- `.small` will apply the same styles as ``. +- `.text-decoration-underline` will apply the same styles as ``. +- `.text-decoration-line-through` will apply the same styles as ``. + +While not shown above, feel free to use `` and `` in HTML5. `` is meant to highlight words or phrases without conveying additional importance, while `` is mostly for voice, technical terms, etc. + +## Text utilities + +Change text alignment, transform, style, weight, line-height, decoration and color with our [text utilities]([[docsref:/utilities/text]]) and [color utilities]([[docsref:/utilities/colors]]). + +## Abbreviations + +Stylized implementation of HTML’s `` element for abbreviations and acronyms to show the expanded version on hover. Abbreviations have a default underline and gain a help cursor to provide additional context on hover and to users of assistive technologies. + +Add `.initialism` to an abbreviation for a slightly smaller font-size. + +attr

      +

      HTML

      `} /> + +## Blockquotes + +For quoting blocks of content from another source within your document. Wrap `
      ` around any HTML as the quote. + + +

      A well-known quote, contained in a blockquote element.

      +
      `} /> + +### Naming a source + +The HTML spec requires that blockquote attribution be placed outside the `
      `. When providing attribution, wrap your `
      ` in a `
      ` and use a `
      ` or a block level element (e.g., `

      `) with the `.blockquote-footer` class. Be sure to wrap the name of the source work in `` as well. + + +

      +

      A well-known quote, contained in a blockquote element.

      +
      + +
      `} /> + +### Alignment + +Use text utilities as needed to change the alignment of your blockquote. + + +
      +

      A well-known quote, contained in a blockquote element.

      +
      + + `} /> + + +
      +

      A well-known quote, contained in a blockquote element.

      +
      + + `} /> + +## Lists + +### Unstyled + +Remove the default `list-style` and left margin on list items (immediate children only). **This only applies to immediate children list items**, meaning you will need to add the class for any nested lists as well. + + +
    5. This is a list.
    6. +
    7. It appears completely unstyled.
    8. +
    9. Structurally, it’s still a list.
    10. +
    11. However, this style only applies to immediate child elements.
    12. +
    13. Nested lists: +
        +
      • are unaffected by this style
      • +
      • will still show a bullet
      • +
      • and have appropriate left margin
      • +
      +
    14. +
    15. This may still come in handy in some situations.
    16. + `} /> + +### Inline + +Remove a list’s bullets and apply some light `margin` with a combination of two classes, `.list-inline` and `.list-inline-item`. + + +
    17. This is a list item.
    18. +
    19. And another one.
    20. +
    21. But they’re displayed inline.
    22. + `} /> + +### Description list alignment + +Align terms and descriptions horizontally by using our grid system’s predefined classes (or semantic mixins). For longer terms, you can optionally add a `.text-truncate` class to truncate the text with an ellipsis. + + +
      Description lists
      +
      A description list is perfect for defining terms.
      + +
      Term
      +
      +

      Definition for the term.

      +

      And some more placeholder definition text.

      +
      + +
      Another term
      +
      This definition is short, so no extra paragraphs or anything.
      + +
      Truncated term is truncated
      +
      This can be useful when space is tight. Adds an ellipsis at the end.
      + +
      Nesting
      +
      +
      +
      Nested definition list
      +
      I heard you like definition lists. Let me put a definition list inside your definition list.
      +
      +
      + `} /> + +## Responsive font sizes + +In Bootstrap 5, we’ve enabled responsive font sizes by default, allowing text to scale more naturally across device and viewport sizes. Have a look at the [RFS page]([[docsref:/getting-started/rfs]]) to find out how this works. + +## CSS + +### Sass variables + +Headings have some dedicated variables for sizing and spacing. + + + +Miscellaneous typography elements covered here and in [Reboot]([[docsref:/content/reboot]]) also have dedicated variables. + + + +### Sass mixins + +There are no dedicated mixins for typography, but Bootstrap does use [Responsive Font Sizing (RFS)]([[docsref:/getting-started/rfs]]). diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color-modes.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color-modes.mdx new file mode 100644 index 00000000..79dd7f6a --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color-modes.mdx @@ -0,0 +1,253 @@ +--- +title: Color modes +description: Bootstrap now supports color modes, or themes, as of v5.3.0. Explore our default light color mode and the new dark mode, or create your own using our styles as your template. +toc: true +added: + version: "5.3" +--- + +import { getDocsRelativePath } from '@libs/path' + + +**Try it yourself!** Download the source code and working demo for using Bootstrap with Stylelint, and the color modes from the [twbs/examples repository](https://github.com/twbs/examples/tree/main/color-modes). You can also [open the example in StackBlitz](https://stackblitz.com/github/twbs/examples/tree/main/color-modes?file=index.html). + + +## Dark mode + +**Bootstrap now supports color modes, starting with dark mode!** With v5.3.0 you can implement your own color mode toggler (see below for an example from Bootstrap’s docs) and apply the different color modes as you see fit. We support a light mode (default) and now dark mode. Color modes can be toggled globally on the `` element, or on specific components and elements, thanks to the `data-bs-theme` attribute. + +Alternatively, you can also switch to a media query implementation thanks to our color mode mixin—see [the usage section for details](#building-with-sass). Heads up though—this eliminates your ability to change themes on a per-component basis as shown below. + +## Example + +For example, to change the color mode of a dropdown menu, add `data-bs-theme="light"` or `data-bs-theme="dark"` to the parent `.dropdown`. Now, no matter the global color mode, these dropdowns will display with the specified theme value. + + + + + + + `} /> + +## How it works + +- As shown above, color mode styles are controlled by the `data-bs-theme` attribute. This attribute can be applied to the `` element, or to any other element or Bootstrap component. If applied to the `` element, it will apply to everything. If applied to a component or element, it will be scoped to that specific component or element. + +- For each color mode you wish to support, you’ll need to add new overrides for the shared global CSS variables. We do this already in our `_root.scss` stylesheet for dark mode, with light mode being the default values. In writing color mode specific styles, use the mixin: + + ```scss + // Color mode variables in _root.scss + @include color-mode(dark) { + // CSS variable overrides here... + } + ``` + +- We use a custom `_variables-dark.scss` to power those shared global CSS variable overrides for dark mode. This file isn’t required for your own custom color modes, but it’s required for our dark mode for two reasons. First, it’s better to have a single place to reset global colors. Second, some Sass variables had to be overridden for background images embedded in our CSS for accordions, form components, and more. + +## Usage + +### Enable dark mode + +Enable the built in dark color mode across your entire project by adding the `data-bs-theme="dark"` attribute to the `` element. This will apply the dark color mode to all components and elements, other than those with a specific `data-bs-theme` attribute applied. Building on the [quick start template]([[docsref:/getting-started/introduction#quick-start]]): + +```html + + + + + + Bootstrap demo + + + +

      Hello, world!

      + + + +``` + +Bootstrap does not yet ship with a built-in color mode picker, but you can use the one from our own documentation if you like. [Learn more in the JavaScript section.](#javascript) + +### Building with Sass + +Our new dark mode option is available to use for all users of Bootstrap, but it’s controlled via data attributes instead of media queries and does not automatically toggle your project’s color mode. You can disable our dark mode entirely via Sass by changing `$enable-dark-mode` to `false`. + +We use a custom Sass mixin, `color-mode()`, to help you control _how_ color modes are applied. By default, we use a `data` attribute approach, allowing you to create more user-friendly experiences where your visitors can choose to have an automatic dark mode or control their preference (like in our own docs here). This is also an easy and scalable way to add different themes and more custom color modes beyond light and dark. + +In case you want to use media queries and only make color modes automatic, you can change the mixin’s default type via Sass variable. Consider the following snippet and its compiled CSS output. + +```scss +$color-mode-type: data; + +@include color-mode(dark) { + .element { + color: var(--bs-primary-text-emphasis); + background-color: var(--bs-primary-bg-subtle); + } +} +``` + +Outputs to: + +```css +[data-bs-theme=dark] .element { + color: var(--bs-primary-text-emphasis); + background-color: var(--bs-primary-bg-subtle); +} +``` + +And when setting to `media-query`: + +```scss +$color-mode-type: media-query; + +@include color-mode(dark) { + .element { + color: var(--bs-primary-text-emphasis); + background-color: var(--bs-primary-bg-subtle); + } +} +``` + +Outputs to: + +```css +@media (prefers-color-scheme: dark) { + .element { + color: var(--bs-primary-text-emphasis); + background-color: var(--bs-primary-bg-subtle); + } +} +``` + +## Custom color modes + +While the primary use case for color modes is light and dark mode, custom color modes are also possible. Create your own `data-bs-theme` selector with a custom value as the name of your color mode, then modify our Sass and CSS variables as needed. We opted to create a separate `_variables-dark.scss` stylesheet to house Bootstrap’s dark mode specific Sass variables, but that’s not required for you. + +For example, you can create a “blue theme” with the selector `data-bs-theme="blue"`. In your custom Sass or CSS file, add the new selector and override any global or component CSS variables as needed. If you’re using Sass, you can also use Sass’s functions within your CSS variable overrides. + + + + +
      Example blue theme
      +

      Some paragraph text to show how the blue theme might look with written copy.

      + +
      + + +`} /> + +```html +
      + ... +
      +``` + +## JavaScript + +To allow visitors or users to toggle color modes, you’ll need to create a toggle element to control the `data-bs-theme` attribute on the root element, ``. We’ve built a toggler in our documentation that initially defers to a user’s current system color mode, but provides an option to override that and pick a specific color mode. + +Here’s a look at the JavaScript that powers it. Feel free to inspect our own documentation navbar to see how it’s implemented using HTML and CSS from our own components. It is suggested to include the JavaScript at the top of your page to reduce potential screen flickering during reloading of your site. Note that if you decide to use media queries for your color modes, your JavaScript may need to be modified or removed if you prefer an implicit control. + + + +## Adding theme colors + +Adding a new color in `$theme-colors` is not enough for some of our components like [alerts]([[docsref:/components/alerts]]) and [list groups]([[docsref:/components/list-group]]). New colors must also be defined in `$theme-colors-text`, `$theme-colors-bg-subtle`, and `$theme-colors-border-subtle` for light theme; but also in `$theme-colors-text-dark`, `$theme-colors-bg-subtle-dark`, and `$theme-colors-border-subtle-dark` for dark theme. + +This is a manual process because Sass cannot generate its own Sass variables from an existing variable or map. In future versions of Bootstrap, we'll revisit this setup to reduce the duplication. + +```scss +// Required +@import "functions"; +@import "variables"; +@import "variables-dark"; + +// Add a custom color to $theme-colors +$custom-colors: ( + "custom-color": #712cf9 +); +$theme-colors: map-merge($theme-colors, $custom-colors); + +@import "maps"; +@import "mixins"; +@import "utilities"; + +// Add a custom color to new theme maps + +// Light mode +$custom-colors-text: ("custom-color": #712cf9); +$custom-colors-bg-subtle: ("custom-color": #e1d2fe); +$custom-colors-border-subtle: ("custom-color": #bfa1fc); + +$theme-colors-text: map-merge($theme-colors-text, $custom-colors-text); +$theme-colors-bg-subtle: map-merge($theme-colors-bg-subtle, $custom-colors-bg-subtle); +$theme-colors-border-subtle: map-merge($theme-colors-border-subtle, $custom-colors-border-subtle); + +// Dark mode +$custom-colors-text-dark: ("custom-color": #e1d2f2); +$custom-colors-bg-subtle-dark: ("custom-color": #8951fa); +$custom-colors-border-subtle-dark: ("custom-color": #e1d2f2); + +$theme-colors-text-dark: map-merge($theme-colors-text-dark, $custom-colors-text-dark); +$theme-colors-bg-subtle-dark: map-merge($theme-colors-bg-subtle-dark, $custom-colors-bg-subtle-dark); +$theme-colors-border-subtle-dark: map-merge($theme-colors-border-subtle-dark, $custom-colors-border-subtle-dark); + +// Remainder of Bootstrap imports +@import "root"; +@import "reboot"; +// etc +``` + +## CSS + +### Variables + +Dozens of root level CSS variables are repeated as overrides for dark mode. These are scoped to the color mode selector, which defaults to `data-bs-theme` but [can be configured](#building-with-sass) to use a `prefers-color-scheme` media query. Use these variables as a guideline for generating your own new color modes. + + + +### Sass variables + +CSS variables for our dark color mode are partially generated from dark mode specific Sass variables in `_variables-dark.scss`. This also includes some custom overrides for changing the colors of embedded SVGs used throughout our components. + + + +### Sass mixins + +Styles for dark mode, and any custom color modes you create, can be scoped appropriately to the `data-bs-theme` attribute selector or media query with the customizable `color-mode()` mixin. See the [Sass usage section](#building-with-sass) for more details. + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color.mdx new file mode 100644 index 00000000..b24f14d6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/color.mdx @@ -0,0 +1,513 @@ +--- +title: Color +description: Bootstrap is supported by an extensive color system that themes our styles and components. This enables more comprehensive customization and extension for any project. +toc: true +--- + +import { getData } from '@libs/data' +import { getSequence } from '@libs/utils' + +## Colors + + + +Bootstrap’s color palette has continued to expand and become more nuanced in v5.3.0. We’ve added new variables for `secondary` and `tertiary` text and background colors, plus `{color}-bg-subtle`, `{color}-border-subtle`, and `{color}-text-emphasis` for our theme colors. These new colors are available through Sass and CSS variables (but not our color maps or utility classes) with the express goal of making it easier to customize across multiple colors modes like light and dark. These new variables are globally set on `:root` and are adapted for our new dark color mode while our original theme colors remain unchanged. + +Colors ending in `-rgb` provide the `red, green, blue` values for use in `rgb()` and `rgba()` color modes. For example, `rgba(var(--bs-secondary-bg-rgb), .5)`. + + +**Heads up!** There’s some potential confusion with our new secondary and tertiary colors, and our existing secondary theme color, as well as our light and dark theme colors. Expect this to be ironed out in v6. + + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      DescriptionSwatchVariables
      + **Body —** Default foreground (color) and background, including components. + +
       
      +
      + `--bs-body-color`
      `--bs-body-color-rgb` +
      +
       
      +
      + `--bs-body-bg`
      `--bs-body-bg-rgb` +
      + **Secondary —** Use the `color` option for lighter text. Use the `bg` option for dividers and to indicate disabled component states. + +
       
      +
      + `--bs-secondary-color`
      `--bs-secondary-color-rgb` +
      +
       
      +
      + `--bs-secondary-bg`
      `--bs-secondary-bg-rgb` +
      + **Tertiary —** Use the `color` option for even lighter text. Use the `bg` option to style backgrounds for hover states, accents, and wells. + +
       
      +
      + `--bs-tertiary-color`
      `--bs-tertiary-color-rgb` +
      +
       
      +
      + `--bs-tertiary-bg`
      `--bs-tertiary-bg-rgb` +
      + **Emphasis —** For higher contrast text. Not applicable for backgrounds. + +
       
      +
      + `--bs-emphasis-color`
      `--bs-emphasis-color-rgb` +
      + **Border —** For component borders, dividers, and rules. Use `--bs-border-color-translucent` to blend with backgrounds with an `rgba()` value. + +
       
      +
      + `--bs-border-color`
      `--bs-border-color-rgb` +
      + **Primary —** Main theme color, used for hyperlinks, focus styles, and component and form active states. + +
       
      +
      + `--bs-primary`
      `--bs-primary-rgb` +
      +
       
      +
      + `--bs-primary-bg-subtle` +
      +
       
      +
      + `--bs-primary-border-subtle` +
      +
      Text
      +
      + `--bs-primary-text-emphasis` +
      + **Success —** Theme color used for positive or successful actions and information. + +
       
      +
      + `--bs-success`
      `--bs-success-rgb` +
      +
       
      +
      + `--bs-success-bg-subtle` +
      +
       
      +
      + `--bs-success-border-subtle` +
      +
      Text
      +
      + `--bs-success-text-emphasis` +
      + **Danger —** Theme color used for errors and dangerous actions. + +
       
      +
      + `--bs-danger`
      `--bs-danger-rgb` +
      +
       
      +
      + `--bs-danger-bg-subtle` +
      +
       
      +
      + `--bs-danger-border-subtle` +
      +
      Text
      +
      + `--bs-danger-text-emphasis` +
      + **Warning —** Theme color used for non-destructive warning messages. + +
       
      +
      + `--bs-warning`
      `--bs-warning-rgb` +
      +
       
      +
      + `--bs-warning-bg-subtle` +
      +
       
      +
      + `--bs-warning-border-subtle` +
      +
      Text
      +
      + `--bs-warning-text-emphasis` +
      + **Info —** Theme color used for neutral and informative content. + +
       
      +
      + `--bs-info`
      `--bs-info-rgb` +
      +
       
      +
      + `--bs-info-bg-subtle` +
      +
       
      +
      + `--bs-info-border-subtle` +
      +
      Text
      +
      + `--bs-info-text-emphasis` +
      + **Light —** Additional theme option for less contrasting colors. + +
       
      +
      + `--bs-light`
      `--bs-light-rgb` +
      +
       
      +
      + `--bs-light-bg-subtle` +
      +
       
      +
      + `--bs-light-border-subtle` +
      +
      Text
      +
      + `--bs-light-text-emphasis` +
      + **Dark —** Additional theme option for higher contrasting colors. + +
       
      +
      + `--bs-dark`
      `--bs-dark-rgb` +
      +
       
      +
      + `--bs-dark-bg-subtle` +
      +
       
      +
      + `--bs-dark-border-subtle` +
      +
      Text
      +
      + `--bs-dark-text-emphasis` +
      +
      + +### Using the new colors + +These new colors are accessible via CSS variables and utility classes—like `--bs-primary-bg-subtle` and `.bg-primary-subtle`—allowing you to compose your own CSS rules with the variables, or to quickly apply styles via classes. The utilities are built with the color’s associated CSS variables, and since we customize those CSS variables for dark mode, they are also adaptive to color mode by default. + + + Example element with utilities + `} /> + +### Theme colors + +We use a subset of all colors to create a smaller color palette for generating color schemes, also available as Sass variables and a Sass map in Bootstrap’s `scss/_variables.scss` file. + +
      + {getData('theme-colors').map((themeColor) => { + return ( +
      +
      {themeColor.title}
      +
      + ) + })} +
      + +All these colors are available as a Sass map, `$theme-colors`. + + + +Check out [our Sass maps and loops docs]([[docsref:/customize/sass#maps-and-loops]]) for how to modify these colors. + +### All colors + +All Bootstrap colors are available as Sass variables and a Sass map in `scss/_variables.scss` file. To avoid increased file sizes, we don’t create text or background color classes for each of these variables. Instead, we choose a subset of these colors for a [theme palette](#theme-colors). + +Be sure to monitor contrast ratios as you customize colors. As shown below, we’ve added three contrast ratios to each of the main colors—one for the swatch’s current colors, one for against white, and one for against black. + +
      + {getData('colors').map((color) => { + if ((color.name !== "white") && (color.name !== "gray") && (color.name !== "gray-dark")) { + return ( +
      +
      + ${color.name} + {color.hex} +
      + + {getSequence(100, 900, 100).map((value) => { + return ( +
      ${color.name}-{value}
      + ) + })} +
      + ) + } + })} + +
      +
      $gray-500#adb5bd
      + {getData('grays').map((gray) => { + return ( +
      $gray-{gray.name}
      + ) + })} +
      + +
      +
      + $black + #000 +
      +
      + $white + #fff +
      +
      +
      + +### Notes on Sass + +Sass cannot programmatically generate variables, so we manually created variables for every tint and shade ourselves. We specify the midpoint value (e.g., `$blue-500`) and use custom color functions to tint (lighten) or shade (darken) our colors via Sass’s `mix()` color function. + +Using `mix()` is not the same as `lighten()` and `darken()`—the former blends the specified color with white or black, while the latter only adjusts the lightness value of each color. The result is a much more complete suite of colors, as [shown in this CodePen demo](https://codepen.io/emdeoh/pen/zYOQOPB). + +Our `tint-color()` and `shade-color()` functions use `mix()` alongside our `$theme-color-interval` variable, which specifies a stepped percentage value for each mixed color we produce. See the `scss/_functions.scss` and `scss/_variables.scss` files for the full source code. + +## Color Sass maps + +Bootstrap’s source Sass files include three maps to help you quickly and easily loop over a list of colors and their hex values. + +- `$colors` lists all our available base (`500`) colors +- `$theme-colors` lists all semantically named theme colors (shown below) +- `$grays` lists all tints and shades of gray + +Within `scss/_variables.scss`, you’ll find Bootstrap’s color variables and Sass map. Here’s an example of the `$colors` Sass map: + + + +Add, remove, or modify values within the map to update how they’re used in many other components. Unfortunately at this time, not _every_ component utilizes this Sass map. Future updates will strive to improve upon this. Until then, plan on making use of the `${color}` variables and this Sass map. + +### Example + +Here’s how you can use these in your Sass: + +```scss +.alpha { color: $purple; } +.beta { + color: $yellow-300; + background-color: $indigo-900; +} +``` + +[Color]([[docsref:/utilities/colors]]) and [background]([[docsref:/utilities/background]]) utility classes are also available for setting `color` and `background-color` using the `500` color values. + +## Generating utilities + + + +Bootstrap doesn’t include `color` and `background-color` utilities for every color variable, but you can generate these yourself with our [utility API]([[docsref:/utilities/api]]) and our extended Sass maps added in v5.1.0. + +1. To start, make sure you’ve imported our functions, variables, mixins, and utilities. +2. Use our `map-merge-multiple()` function to quickly merge multiple Sass maps together in a new map. +3. Merge this new combined map to extend any utility with a `{color}-{level}` class name. + +Here’s an example that generates text color utilities (e.g., `.text-purple-500`) using the above steps. + +```scss +@import "bootstrap/scss/functions"; +@import "bootstrap/scss/variables"; +@import "bootstrap/scss/variables-dark"; +@import "bootstrap/scss/maps"; +@import "bootstrap/scss/mixins"; +@import "bootstrap/scss/utilities"; + +$all-colors: map-merge-multiple($blues, $indigos, $purples, $pinks, $reds, $oranges, $yellows, $greens, $teals, $cyans); + +$utilities: map-merge( + $utilities, + ( + "color": map-merge( + map-get($utilities, "color"), + ( + values: map-merge( + map-get(map-get($utilities, "color"), "values"), + ( + $all-colors + ), + ), + ), + ), + ) +); + +@import "bootstrap/scss/utilities/api"; +``` + +This will generate new `.text-{color}-{level}` utilities for every color and level. You can do the same for any other utility and property as well. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/components.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/components.mdx new file mode 100644 index 00000000..2aa7e855 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/components.mdx @@ -0,0 +1,75 @@ +--- +title: Components +description: Learn how and why we build nearly all our components responsively and with base and modifier classes. +toc: true +--- + +## Base classes + +Bootstrap’s components are largely built with a base-modifier nomenclature. We group as many shared properties as possible into a base class, like `.btn`, and then group individual styles for each variant into modifier classes, like `.btn-primary` or `.btn-success`. + +To build our modifier classes, we use Sass’s `@each` loops to iterate over a Sass map. This is especially helpful for generating variants of a component by our `$theme-colors` and creating responsive variants for each breakpoint. As you customize these Sass maps and recompile, you’ll automatically see your changes reflected in these loops. + +Check out [our Sass maps and loops docs]([[docsref:/customize/sass#maps-and-loops]]) for how to customize these loops and extend Bootstrap’s base-modifier approach to your own code. + +## Modifiers + +Many of Bootstrap’s components are built with a base-modifier class approach. This means the bulk of the styling is contained to a base class (e.g., `.btn`) while style variations are confined to modifier classes (e.g., `.btn-danger`). These modifier classes are built from the `$theme-colors` map to make customizing the number and name of our modifier classes. + +Here are two examples of how we loop over the `$theme-colors` map to generate modifiers to the `.alert` and `.list-group` components. + + + + + +## Responsive + +These Sass loops aren’t limited to color maps, either. You can also generate responsive variations of your components. Take for example our responsive alignment of the dropdowns where we mix an `@each` loop for the `$grid-breakpoints` Sass map with a media query include. + + + +Should you modify your `$grid-breakpoints`, your changes will apply to all the loops iterating over that map. + + + +For more information and examples on how to modify our Sass maps and variables, please refer to [the CSS section of the Grid documentation]([[docsref:/layout/grid#css]]). + +## Creating your own + +We encourage you to adopt these guidelines when building with Bootstrap to create your own components. We’ve extended this approach ourselves to the custom components in our documentation and examples. Components like our callouts are built just like our provided components with base and modifier classes. + +
      +
      + This is a callout. We built it custom for our docs so our messages to you stand out. It has three variants via modifier classes. +
      +
      + +```html +
      ...
      +``` + +In your CSS, you’d have something like the following where the bulk of the styling is done via `.callout`. Then, the unique styles between each variant is controlled via modifier class. + +```scss +// Base class +.callout {} + +// Modifier classes +.callout-info {} +.callout-warning {} +.callout-danger {} +``` + +For the callouts, that unique styling is just a `border-left-color`. When you combine that base class with one of those modifier classes, you get your complete component family: + + +**This is an info callout.** Example text to show it in action. + + + +**This is a warning callout.** Example text to show it in action. + + + +**This is a danger callout.** Example text to show it in action. + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/css-variables.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/css-variables.mdx new file mode 100644 index 00000000..20a0b9d4 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/css-variables.mdx @@ -0,0 +1,70 @@ +--- +title: CSS variables +description: Use Bootstrap’s CSS custom properties for fast and forward-looking design and development. +toc: true +--- + +Bootstrap includes many [CSS custom properties (variables)](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) in its compiled CSS for real-time customization without the need to recompile Sass. These provide easy access to commonly used values like our theme colors, breakpoints, and primary font stacks when working in your browser’s inspector, a code sandbox, or general prototyping. + +**All our custom properties are prefixed with `bs-`** to avoid conflicts with third party CSS. + +## Root variables + +Here are the variables we include (note that the `:root` is required) that can be accessed anywhere Bootstrap’s CSS is loaded. They’re located in our `_root.scss` file and included in our compiled dist files. + +### Default + +These CSS variables are available everywhere, regardless of color mode. + + + +### Dark mode + +These variables are scoped to our built-in dark mode. + + + +## Component variables + +Bootstrap 5 is increasingly making use of custom properties as local variables for various components. This way we reduce our compiled CSS, ensure styles aren’t inherited in places like nested tables, and allow some basic restyling and extending of Bootstrap components after Sass compilation. + +Have a look at our table documentation for some [insight into how we’re using CSS variables]([[docsref:/content/tables#how-do-the-variants-and-accented-tables-work]]). Our [navbars also use CSS variables]([[docsref:/components/navbar#css]]) as of v5.2.0. We’re also using CSS variables across our grids—primarily for gutters the [new opt-in CSS grid]([[docsref:/layout/css-grid]])—with more component usage coming in the future. + +Whenever possible, we'll assign CSS variables at the base component level (e.g., `.navbar` for navbar and its sub-components). This reduces guessing on where and how to customize, and allows for easy modifications by our team in future updates. + +## Prefix + +Most CSS variables use a prefix to avoid collisions with your own codebase. This prefix is in addition to the `--` that’s required on every CSS variable. + +Customize the prefix via the `$prefix` Sass variable. By default, it’s set to `bs-` (note the trailing dash). + +## Examples + +CSS variables offer similar flexibility to Sass’s variables, but without the need for compilation before being served to the browser. For example, here we’re resetting our page’s font and link styles with CSS variables. + +```css +body { + font: 1rem/1.5 var(--bs-font-sans-serif); +} +a { + color: var(--bs-blue); +} +``` + +## Focus variables + + + +Bootstrap provides custom `:focus` styles using a combination of Sass and CSS variables that can be optionally added to specific components and elements. We do not yet globally override all `:focus` styles. + +In our Sass, we set default values that can be customized before compiling. + + + +Those variables are then reassigned to `:root` level CSS variables that can be customized in real-time, including with options for `x` and `y` offsets (which default to their fallback value of `0`). + + + +## Grid breakpoints + +While we include our grid breakpoints as CSS variables (except for `xs`), be aware that **CSS variables do not work in media queries**. This is by design in the CSS spec for variables, but may change in coming years with support for `env()` variables. Check out [this Stack Overflow answer](https://stackoverflow.com/a/47212942) for some helpful links. In the meantime, you can use these variables in other CSS situations, as well as in your JavaScript. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/optimize.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/optimize.mdx new file mode 100644 index 00000000..0384ca05 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/optimize.mdx @@ -0,0 +1,88 @@ +--- +title: Optimize +description: Keep your projects lean, responsive, and maintainable so you can deliver the best experience and focus on more important jobs. +toc: true +--- + +## Lean Sass imports + +When using Sass in your asset pipeline, make sure you optimize Bootstrap by only `@import`ing the components you need. Your largest optimizations will likely come from the `Layout & Components` section of our `bootstrap.scss`. + + + + +If you’re not using a component, comment it out or delete it entirely. For example, if you’re not using the carousel, remove that import to save some file size in your compiled CSS. Keep in mind there are some dependencies across Sass imports that may make it more difficult to omit a file. + +## Lean JavaScript + +Bootstrap’s JavaScript includes every component in our primary dist files (`bootstrap.js` and `bootstrap.min.js`), and even our primary dependency (Popper) with our bundle files (`bootstrap.bundle.js` and `bootstrap.bundle.min.js`). While you’re customizing via Sass, be sure to remove related JavaScript. + +For instance, assuming you’re using your own JavaScript bundler like Webpack, Parcel, or Vite, you’d only import the JavaScript you plan on using. In the example below, we show how to just include our modal JavaScript: + +```js +// Import just what we need + +// import 'bootstrap/js/dist/alert'; +// import 'bootstrap/js/dist/button'; +// import 'bootstrap/js/dist/carousel'; +// import 'bootstrap/js/dist/collapse'; +// import 'bootstrap/js/dist/dropdown'; +import 'bootstrap/js/dist/modal'; +// import 'bootstrap/js/dist/offcanvas'; +// import 'bootstrap/js/dist/popover'; +// import 'bootstrap/js/dist/scrollspy'; +// import 'bootstrap/js/dist/tab'; +// import 'bootstrap/js/dist/toast'; +// import 'bootstrap/js/dist/tooltip'; +``` + +This way, you’re not including any JavaScript you don’t intend to use for components like buttons, carousels, and tooltips. If you’re importing dropdowns, tooltips or popovers, be sure to list the Popper dependency in your `package.json` file. + + +**Heads up!** Files in `bootstrap/js/dist` use the **default export**. To use them, do the following: + +```js +import Modal from 'bootstrap/js/dist/modal' +const modal = new Modal(document.getElementById('myModal')) +``` + + +## Autoprefixer .browserslistrc + +Bootstrap depends on Autoprefixer to automatically add browser prefixes to certain CSS properties. Prefixes are dictated by our `.browserslistrc` file, found in the root of the Bootstrap repo. Customizing this list of browsers and recompiling the Sass will automatically remove some CSS from your compiled CSS, if there are vendor prefixes unique to that browser or version. + +## Unused CSS + +_Help wanted with this section, please consider opening a PR. Thanks!_ + +While we don’t have a prebuilt example for using [PurgeCSS](https://github.com/FullHuman/purgecss) with Bootstrap, there are some helpful articles and walkthroughs that the community has written. Here are some options: + +- https://medium.com/dwarves-foundation/remove-unused-css-styles-from-bootstrap-using-purgecss-88395a2c5772 +- https://lukelowrey.com/automatically-removeunused-css-from-bootstrap-or-other-frameworks/ + +Lastly, this [CSS Tricks article on unused CSS](https://css-tricks.com/how-do-you-remove-unused-css-from-a-site/) shows how to use PurgeCSS and other similar tools. + +## Minify and gzip + +Whenever possible, be sure to compress all the code you serve to your visitors. If you’re using Bootstrap dist files, try to stick to the minified versions (indicated by the `.min.css` and `.min.js` extensions). If you’re building Bootstrap from the source with your own build system, be sure to implement your own minifiers for HTML, CSS, and JS. + +## Non-blocking files + +While minifying and using compression might seem like enough, making your files non-blocking ones is also a big step in making your site well-optimized and fast enough. + +If you are using a [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview/) plugin in Google Chrome, you may have stumbled over FCP. [The First Contentful Paint](https://web.dev/articles/fcp) metric measures the time from when the page starts loading to when any part of the page’s content is rendered on the screen. + +You can improve FCP by deferring non-critical JavaScript or CSS. What does that mean? Simply, JavaScript or stylesheets that don’t need to be present on the first paint of your page should be marked with `async` or `defer` attributes. + +This ensures that the less important resources are loaded later and not blocking the first paint. On the other hand, critical resources can be included as inline scripts or styles. + +If you want to learn more about this, there are already a lot of great articles about it: + +- https://developer.chrome.com/docs/lighthouse/performance/render-blocking-resources/ +- https://web.dev/articles/defer-non-critical-css + +## Always use HTTPS + +Your website should only be available over HTTPS connections in production. HTTPS improves the security, privacy, and availability of all sites, and [there is no such thing as non-sensitive web traffic](https://https.cio.gov/everything/). The steps to configure your website to be served exclusively over HTTPS vary widely depending on your architecture and web hosting provider, and thus are beyond the scope of these docs. + +Sites served over HTTPS should also access all stylesheets, scripts, and other assets over HTTPS connections. Otherwise, you’ll be sending users [mixed active content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content), leading to potential vulnerabilities where a site can be compromised by altering a dependency. This can lead to security issues and in-browser warnings displayed to users. Whether you’re getting Bootstrap from a CDN or serving it yourself, ensure that you only access it over HTTPS connections. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/options.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/options.mdx new file mode 100644 index 00000000..926ae031 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/options.mdx @@ -0,0 +1,31 @@ +--- +title: Options +description: Quickly customize Bootstrap with built-in variables to easily toggle global CSS preferences for controlling style and behavior. +--- + +Customize Bootstrap with our built-in custom variables file and easily toggle global CSS preferences with new `$enable-*` Sass variables. Override a variable’s value and recompile with `npm run test` as needed. + +You can find and customize these variables for key global options in Bootstrap’s `scss/_variables.scss` file. + + +| Variable | Values | Description | +| ------------------------------ | ---------------------------------- | -------------------------------------------------------------------------------------- | +| `$spacer` | `1rem` (default), or any value > 0 | Specifies the default spacer value to programmatically generate our [spacer utilities]([[docsref:/utilities/spacing]]). | +| `$enable-dark-mode` | `true` (default) or `false` | Enables built-in [dark mode support]([[docsref:/customize/color-modes#dark-mode]]) across the project and its components. | +| `$enable-rounded` | `true` (default) or `false` | Enables predefined `border-radius` styles on various components. | +| `$enable-shadows` | `true` or `false` (default) | Enables predefined decorative `box-shadow` styles on various components. Does not affect `box-shadow`s used for focus states. | +| `$enable-gradients` | `true` or `false` (default) | Enables predefined gradients via `background-image` styles on various components. | +| `$enable-transitions` | `true` (default) or `false` | Enables predefined `transition`s on various components. | +| `$enable-reduced-motion` | `true` (default) or `false` | Enables the [`prefers-reduced-motion` media query]([[docsref:/getting-started/accessibility#reduced-motion]]), which suppresses certain animations/transitions based on the users’ browser/operating system preferences. | +| `$enable-grid-classes` | `true` (default) or `false` | Enables the generation of CSS classes for the grid system (e.g. `.row`, `.col-md-1`, etc.). | +| `$enable-cssgrid` | `true` or `false` (default) | Enables the experimental CSS Grid system (e.g. `.grid`, `.g-col-md-1`, etc.). | +| `$enable-container-classes` | `true` (default) or `false` | Enables the generation of CSS classes for layout containers. (New in v5.2.0) | +| `$enable-caret` | `true` (default) or `false` | Enables pseudo element caret on `.dropdown-toggle`. | +| `$enable-button-pointers` | `true` (default) or `false` | Add “hand” cursor to non-disabled button elements. | +| `$enable-rfs` | `true` (default) or `false` | Globally enables [RFS]([[docsref:/getting-started/rfs]]). | +| `$enable-validation-icons` | `true` (default) or `false` | Enables `background-image` icons within textual inputs and some custom forms for validation states. | +| `$enable-negative-margins` | `true` or `false` (default) | Enables the generation of [negative margin utilities]([[docsref:/utilities/spacing#negative-margin]]). | +| `$enable-deprecation-messages` | `true` (default) or `false` | Set to `false` to hide warnings when using any of the deprecated mixins and functions that are planned to be removed in `v6`. | +| `$enable-important-utilities` | `true` (default) or `false` | Enables the `!important` suffix in utility classes. | +| `$enable-smooth-scroll` | `true` (default) or `false` | Applies `scroll-behavior: smooth` globally, except for users asking for reduced motion through [`prefers-reduced-motion` media query]([[docsref:/getting-started/accessibility#reduced-motion]]) | + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/overview.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/overview.mdx new file mode 100644 index 00000000..7acb624e --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/overview.mdx @@ -0,0 +1,51 @@ +--- +title: Customize +description: Learn how to theme, customize, and extend Bootstrap with Sass, a boatload of global options, an expansive color system, and more. +toc: false +aliases: "/docs/[[config:docs_version]]/customize/" +sections: + - title: Sass + description: Utilize our source Sass files to take advantage of variables, maps, mixins, and functions. + - title: Options + description: Customize Bootstrap with built-in variables to easily toggle global CSS preferences. + - title: Color + description: Learn about and customize the color systems that support the entire toolkit. + - title: Color modes + description: Explore our default light mode and the new dark mode, or create custom color modes yourself. + - title: Components + description: Learn how we build nearly all our components responsively and with base and modifier classes. + - title: CSS variables + description: Use Bootstrap’s CSS custom properties for fast and forward-looking design and development. + - title: Optimize + description: Keep your projects lean, responsive, and maintainable so you can deliver the best experience. +--- + +## Overview + +There are multiple ways to customize Bootstrap. Your best path can depend on your project, the complexity of your build tools, the version of Bootstrap you’re using, browser support, and more. + +Our two preferred methods are: + +1. Using Bootstrap [via package manager]([[docsref:/getting-started/download#package-managers]]) so you can use and extend our source files. +2. Using Bootstrap’s compiled distribution files or [jsDelivr]([[docsref:/getting-started/download#cdn-via-jsdelivr]]) so you can add onto or override Bootstrap’s styles. + +While we cannot go into details here on how to use every package manager, we can give some guidance on [using Bootstrap with your own Sass compiler]([[docsref:/customize/sass]]). + +For those who want to use the distribution files, review the [getting started page]([[docsref:/getting-started/introduction]]) for how to include those files and an example HTML page. From there, consult the docs for the layout, components, and behaviors you’d like to use. + +As you familiarize yourself with Bootstrap, continue exploring this section for more details on how to utilize our global options, making use of and changing our color system, how we build our components, how to use our growing list of CSS custom properties, and how to optimize your code when building with Bootstrap. + +## CSPs and embedded SVGs + +Several Bootstrap components include embedded SVGs in our CSS to style components consistently and easily across browsers and devices. **For organizations with more strict CSP configurations**, we’ve documented all instances of our embedded SVGs (all of which are applied via `background-image`) so you can more thoroughly review your options. + +- [Accordion]([[docsref:/components/accordion]]) +- [Carousel controls]([[docsref:/components/carousel#with-controls]]) +- [Close button]([[docsref:/components/close-button]]) (used in alerts and modals) +- [Form checkboxes and radio buttons]([[docsref:/forms/checks-radios]]) +- [Form switches]([[docsref:/forms/checks-radios#switches]]) +- [Form validation icons]([[docsref:/forms/validation#server-side]]) +- [Navbar toggle buttons]([[docsref:/components/navbar#responsive-behaviors]]) +- [Select menus]([[docsref:/forms/select]]) + +Based on [community conversation](https://github.com/twbs/bootstrap/issues/25394), some options for addressing this in your own codebase include [replacing the URLs with locally hosted assets]([[docsref:/getting-started/webpack#extracting-svg-files]]), removing the images and using inline images (not possible in all components), and modifying your CSP. Our recommendation is to carefully review your own security policies and decide on the best path forward, if necessary. diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/sass.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/sass.mdx new file mode 100644 index 00000000..6352de40 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/customize/sass.mdx @@ -0,0 +1,363 @@ +--- +title: Sass +description: Utilize our source Sass files to take advantage of variables, maps, mixins, and functions to help you build faster and customize your project. +toc: true +--- + +Utilize our source Sass files to take advantage of variables, maps, mixins, and more. + + +Sass deprecation warnings are shown when compiling source Sass files with the latest versions of Dart Sass. This does not prevent compilation or usage of Bootstrap. We’re [working on a long-term fix]([[config:repo]]/issues/40962), but in the meantime these deprecation notices can be ignored. + + +## File structure + +Whenever possible, avoid modifying Bootstrap’s core files. For Sass, that means creating your own stylesheet that imports Bootstrap so you can modify and extend it. Assuming you’re using a package manager like npm, you’ll have a file structure that looks like this: + +```text +your-project/ +├── scss/ +│ └── custom.scss +└── node_modules/ +│ └── bootstrap/ +│ ├── js/ +│ └── scss/ +└── index.html +``` + +If you’ve downloaded our source files and aren’t using a package manager, you’ll want to manually create something similar to that structure, keeping Bootstrap’s source files separate from your own. + +```text +your-project/ +├── scss/ +│ └── custom.scss +├── bootstrap/ +│ ├── js/ +│ └── scss/ +└── index.html +``` + +## Importing + +In your `custom.scss`, you’ll import Bootstrap’s source Sass files. You have two options: include all of Bootstrap, or pick the parts you need. We encourage the latter, though be aware there are some requirements and dependencies across our components. You also will need to include some JavaScript for our plugins. + +```scss +// Custom.scss +// Option A: Include all of Bootstrap + +// Include any default variable overrides here (though functions won’t be available) + +@import "../node_modules/bootstrap/scss/bootstrap"; + +// Then add additional custom code here +``` + +```scss +// Custom.scss +// Option B: Include parts of Bootstrap + +// 1. Include functions first (so you can manipulate colors, SVGs, calc, etc) +@import "../node_modules/bootstrap/scss/functions"; + +// 2. Include any default variable overrides here + +// 3. Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets) +@import "../node_modules/bootstrap/scss/variables"; +@import "../node_modules/bootstrap/scss/variables-dark"; + +// 4. Include any default map overrides here + +// 5. Include remainder of required parts +@import "../node_modules/bootstrap/scss/maps"; +@import "../node_modules/bootstrap/scss/mixins"; +@import "../node_modules/bootstrap/scss/root"; + +// 6. Include any other optional stylesheet partials as desired; list below is not inclusive of all available stylesheets +@import "../node_modules/bootstrap/scss/utilities"; +@import "../node_modules/bootstrap/scss/reboot"; +@import "../node_modules/bootstrap/scss/type"; +@import "../node_modules/bootstrap/scss/images"; +@import "../node_modules/bootstrap/scss/containers"; +@import "../node_modules/bootstrap/scss/grid"; +@import "../node_modules/bootstrap/scss/helpers"; +// ... + +// 7. Optionally include utilities API last to generate classes based on the Sass map in `_utilities.scss` +@import "../node_modules/bootstrap/scss/utilities/api"; + +// 8. Add additional custom code here +``` + +With that setup in place, you can begin to modify any of the Sass variables and maps in your `custom.scss`. You can also start to add parts of Bootstrap under the `// Optional` section as needed. We suggest using the full import stack from our `bootstrap.scss` file as your starting point. + +## Compiling + +In order to use your custom Sass code as CSS in the browser, you need a Sass compiler. Sass ships as a CLI package, but you can also compile it with other build tools like [Gulp](https://gulpjs.com/) or [Webpack](https://webpack.js.org/), or with GUI applications. Some IDEs also have Sass compilers built in or as downloadable extensions. + +We like to use the CLI to compile our Sass, but you can use whichever method you prefer. From the command line, run the following: + +```sh +# Install Sass globally +npm install -g sass + +# Watch your custom Sass for changes and compile it to CSS +sass --watch ./scss/custom.scss ./css/custom.css +``` + +Learn more about your options at [sass-lang.com/install](https://sass-lang.com/install/) and [compiling with VS Code](https://code.visualstudio.com/docs/languages/css#_transpiling-sass-and-less-into-css). + + +**Using Bootstrap with another build tool?** Consider reading our guides for compiling with [Webpack]([[docsref:/getting-started/webpack]]), [Parcel]([[docsref:/getting-started/parcel]]), or [Vite]([[docsref:/getting-started/vite]]). We also have production-ready demos in [our examples repository on GitHub](https://github.com/twbs/examples). + + +## Including + +Once your CSS is compiled, you can include it in your HTML files. Inside your `index.html` you’ll want to include your compiled CSS file. Be sure to update the path to your compiled CSS file if you’ve changed it. + +```html + + + + + + Custom Bootstrap + + + +

      Hello, world!

      + + +``` + +## Variable defaults + +Every Sass variable in Bootstrap includes the `!default` flag allowing you to override the variable’s default value in your own Sass without modifying Bootstrap’s source code. Copy and paste variables as needed, modify their values, and remove the `!default` flag. If a variable has already been assigned, then it won’t be re-assigned by the default values in Bootstrap. + +You will find the complete list of Bootstrap’s variables in `scss/_variables.scss`. Some variables are set to `null`, these variables don’t output the property unless they are overridden in your configuration. + +Variable overrides must come after our functions are imported, but before the rest of the imports. + +Here’s an example that changes the `background-color` and `color` for the `` when importing and compiling Bootstrap via npm: + +```scss +// Required +@import "../node_modules/bootstrap/scss/functions"; + +// Default variable overrides +$body-bg: #000; +$body-color: #111; + +// Required +@import "../node_modules/bootstrap/scss/variables"; +@import "../node_modules/bootstrap/scss/variables-dark"; +@import "../node_modules/bootstrap/scss/maps"; +@import "../node_modules/bootstrap/scss/mixins"; +@import "../node_modules/bootstrap/scss/root"; + +// Optional Bootstrap components here +@import "../node_modules/bootstrap/scss/reboot"; +@import "../node_modules/bootstrap/scss/type"; +// etc +``` + +Repeat as necessary for any variable in Bootstrap, including the global options below. + + + +## Maps and loops + +Bootstrap includes a handful of Sass maps, key value pairs that make it easier to generate families of related CSS. We use Sass maps for our colors, grid breakpoints, and more. Just like Sass variables, all Sass maps include the `!default` flag and can be overridden and extended. + +Some of our Sass maps are merged into empty ones by default. This is done to allow easy expansion of a given Sass map, but comes at the cost of making _removing_ items from a map slightly more difficult. + +### Modify map + +All variables in the `$theme-colors` map are defined as standalone variables. To modify an existing color in our `$theme-colors` map, add the following to your custom Sass file: + +```scss +$primary: #0074d9; +$danger: #ff4136; +``` + +Later on, these variables are set in Bootstrap’s `$theme-colors` map: + +```scss +$theme-colors: ( + "primary": $primary, + "danger": $danger +); +``` + +### Add to map + +Add new colors to `$theme-colors`, or any other map, by creating a new Sass map with your custom values and merging it with the original map. In this case, we'll create a new `$custom-colors` map and merge it with `$theme-colors`. + +```scss +// Create your own map +$custom-colors: ( + "custom-color": #900 +); + +// Merge the maps +$theme-colors: map-merge($theme-colors, $custom-colors); +``` + +### Remove from map + +To remove colors from `$theme-colors`, or any other map, use `map-remove`. Be aware you must insert `$theme-colors` between our requirements just after its definition in `variables` and before its usage in `maps`: + +```scss +// Required +@import "../node_modules/bootstrap/scss/functions"; +@import "../node_modules/bootstrap/scss/variables"; +@import "../node_modules/bootstrap/scss/variables-dark"; + +$theme-colors: map-remove($theme-colors, "info", "light", "dark"); + +@import "../node_modules/bootstrap/scss/maps"; +@import "../node_modules/bootstrap/scss/mixins"; +@import "../node_modules/bootstrap/scss/root"; + +// Optional +@import "../node_modules/bootstrap/scss/reboot"; +@import "../node_modules/bootstrap/scss/type"; +// etc +``` + +## Required keys + +Bootstrap assumes the presence of some specific keys within Sass maps as we used and extend these ourselves. As you customize the included maps, you may encounter errors where a specific Sass map’s key is being used. + +For example, we use the `primary`, `success`, and `danger` keys from `$theme-colors` for links, buttons, and form states. Replacing the values of these keys should present no issues, but removing them may cause Sass compilation issues. In these instances, you’ll need to modify the Sass code that makes use of those values. + +## Functions + +### Colors + +Next to the [Sass maps]([[docsref:/customize/color#color-sass-maps]]) we have, theme colors can also be used as standalone variables, like `$primary`. + +```scss +.custom-element { + color: $gray-100; + background-color: $dark; +} +``` + +You can lighten or darken colors with Bootstrap’s `tint-color()` and `shade-color()` functions. These functions will mix colors with black or white, unlike Sass’ native `lighten()` and `darken()` functions which will change the lightness by a fixed amount, which often doesn’t lead to the desired effect. + +`shift-color()` combines these two functions by shading the color if the weight is positive and tinting the color if the weight is negative. + + + +In practice, you’d call the function and pass in the color and weight parameters. + +```scss +.custom-element { + color: tint-color($primary, 10%); +} + +.custom-element-2 { + color: shade-color($danger, 30%); +} + +.custom-element-3 { + color: shift-color($success, 40%); + background-color: shift-color($success, -60%); +} +``` + +### Color contrast + +In order to meet the [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/TR/WCAG/) contrast requirements, authors **must** provide a minimum [text color contrast of 4.5:1](https://www.w3.org/TR/WCAG/#contrast-minimum) and a minimum [non-text color contrast of 3:1](https://www.w3.org/TR/WCAG/#non-text-contrast), with very few exceptions. + +To help with this, we included the `color-contrast` function in Bootstrap. It uses the [WCAG contrast ratio algorithm](https://www.w3.org/TR/WCAG/#dfn-contrast-ratio) for calculating contrast thresholds based on [relative luminance](https://www.w3.org/TR/WCAG/#dfn-relative-luminance) in an `sRGB` color space to automatically return a light (`#fff`), dark (`#212529`) or black (`#000`) contrast color based on the specified base color. This function is especially useful for mixins or loops where you’re generating multiple classes. + +For example, to generate color swatches from our `$theme-colors` map: + +```scss +@each $color, $value in $theme-colors { + .swatch-#{$color} { + color: color-contrast($value); + } +} +``` + +It can also be used for one-off contrast needs: + +```scss +.custom-element { + color: color-contrast(#000); // returns `color: #fff` +} +``` + +You can also specify a base color with our color map functions: + +```scss +.custom-element { + color: color-contrast($dark); // returns `color: #fff` +} +``` + +### Escape SVG + +We use the `escape-svg` function to escape the `<`, `>` and `#` characters for SVG background images. When using the `escape-svg` function, data URIs must be quoted. + +### Add and Subtract functions + +We use the `add` and `subtract` functions to wrap the CSS `calc` function. The primary purpose of these functions is to avoid errors when a “unitless” `0` value is passed into a `calc` expression. Expressions like `calc(10px - 0)` will return an error in all browsers, despite being mathematically correct. + +Example where the calc is valid: + +```scss +$border-radius: .25rem; +$border-width: 1px; + +.element { + // Output calc(.25rem - 1px) is valid + border-radius: calc($border-radius - $border-width); +} + +.element { + // Output the same calc(.25rem - 1px) as above + border-radius: subtract($border-radius, $border-width); +} +``` + +Example where the calc is invalid: + +```scss +$border-radius: .25rem; +$border-width: 0; + +.element { + // Output calc(.25rem - 0) is invalid + border-radius: calc($border-radius - $border-width); +} + +.element { + // Output .25rem + border-radius: subtract($border-radius, $border-width); +} +``` + +## Mixins + +Our `scss/mixins/` directory has a ton of mixins that power parts of Bootstrap and can also be used across your own project. + +### Color schemes + +A shorthand mixin for the `prefers-color-scheme` media query is available with support for `light` and `dark` color schemes. See [the color modes documentation]([[docsref:/customize/color-modes]]) for information on our color mode mixin. + + + +```scss +.custom-element { + @include color-scheme(light) { + // Insert light mode styles here + } + + @include color-scheme(dark) { + // Insert dark mode styles here + } +} +``` diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/docsref.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/docsref.mdx new file mode 100644 index 00000000..f6b303e8 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/docsref.mdx @@ -0,0 +1,45 @@ +--- +title: Docs reference +description: Examples of Bootstrap’s documentation-specific components and styles. +aliases: "/docsref/" +toc: true +robots: noindex,follow +--- + +## Buttons + + + + + +## Callouts + + + Default callout + + + + Warning callout + + + + Danger callout + + +## Code example + +```scss +.test { + --color: blue; +} +``` + +
      + The HTML abbreviation element. +
      + +This is a test.`} /> + + + + diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/extend/approach.mdx b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/extend/approach.mdx new file mode 100644 index 00000000..1be156e6 --- /dev/null +++ b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/content/docs/extend/approach.mdx @@ -0,0 +1,84 @@ +--- +title: Approach +description: Learn about the guiding principles, strategies, and techniques used to build and maintain Bootstrap so you can more easily customize and extend it yourself. +aliases: + - "/docs/[[config:docs_version]]/extend/" +--- + +While the getting started pages provide an introductory tour of the project and what it offers, this document focuses on _why_ we do the things we do in Bootstrap. It explains our philosophy to building on the web so that others can learn from us, contribute with us, and help us improve. + +See something that doesn’t sound right, or perhaps could be done better? [Open an issue]([[config:repo]]/issues/new/choose)—we’d love to discuss it with you. + +## Summary + +We'll dive into each of these more throughout, but at a high level, here’s what guides our approach. + +- Components should be responsive and mobile-first +- Components should be built with a base class and extended via modifier classes +- Component states should obey a common z-index scale +- Whenever possible, prefer an HTML and CSS implementation over JavaScript +- Whenever possible, use utilities over custom styles +- Whenever possible, avoid enforcing strict HTML requirements (children selectors) + +## Responsive + +Bootstrap’s responsive styles are built to be responsive, an approach that’s often referred to as _mobile-first_. We use this term in our docs and largely agree with it, but at times it can be too broad. While not every component _must_ be entirely responsive in Bootstrap, this responsive approach is about reducing CSS overrides by pushing you to add styles as the viewport becomes larger. + +Across Bootstrap, you’ll see this most clearly in our media queries. In most cases, we use `min-width` queries that begin to apply at a specific breakpoint and carry up through the higher breakpoints. For example, a `.d-none` applies from `min-width: 0` to infinity. On the other hand, a `.d-md-none` applies from the medium breakpoint and up. + +At times we'll use `max-width` when a component’s inherent complexity requires it. At times, these overrides are functionally and mentally clearer to implement and support than rewriting core functionality from our components. We strive to limit this approach, but will use it from time to time. + +## Classes + +Aside from our Reboot, a cross-browser normalization stylesheet, all our styles aim to use classes as selectors. This means steering clear of type selectors (e.g., `input[type="text"]`) and extraneous parent classes (e.g., `.parent .child`) that make styles too specific to easily override. + +As such, components should be built with a base class that houses common, not-to-be overridden property-value pairs. For example, `.btn` and `.btn-primary`. We use `.btn` for all the common styles like `display`, `padding`, and `border-width`. We then use modifiers like `.btn-primary` to add the color, background-color, border-color, etc. + +Modifier classes should only be used when there are multiple properties or values to be changed across multiple variants. Modifiers are not always necessary, so be sure you’re actually saving lines of code and preventing unnecessary overrides when creating them. Good examples of modifiers are our theme color classes and size variants. + +## z-index scales + +There are two `z-index` scales in Bootstrap—elements within a component and overlay components. + +### Component elements + +- Some components in Bootstrap are built with overlapping elements to prevent double borders without modifying the `border` property. For example, button groups, input groups, and pagination. +- These components share a standard `z-index` scale of `0` through `3`. +- `0` is default (initial), `1` is `:hover`, `2` is `:active`/`.active`, and `3` is `:focus`. +- This approach matches our expectations of highest user priority. If an element is focused, it’s in view and at the user’s attention. Active elements are second highest because they indicate state. Hover is third highest because it indicates user intent, but nearly _anything_ can be hovered. + +### Overlay components + +Bootstrap includes several components that function as an overlay of some kind. This includes, in order of highest `z-index`, dropdowns, fixed and sticky navbars, modals, tooltips, and popovers. These components have their own `z-index` scale that begins at `1000`. This starting number was chosen arbitrarily and serves as a small buffer between our styles and your project’s custom styles. + +Each overlay component increases its `z-index` value slightly in such a way that common UI principles allow user focused or hovered elements to remain in view at all times. For example, a modal is document blocking (e.g., you cannot take any other action save for the modal’s action), so we put that above our navbars. + +Learn more about this in our [`z-index` layout page]([[docsref:/layout/z-index]]). + +## HTML and CSS over JS + +Whenever possible, we prefer to write HTML and CSS over JavaScript. In general, HTML and CSS are more prolific and accessible to more people of all different experience levels. HTML and CSS are also faster in your browser than JavaScript, and your browser generally provides a great deal of functionality for you. + +This principle is our first-class JavaScript API using `data` attributes. You don’t need to write nearly any JavaScript to use our JavaScript plugins; instead, write HTML. Read more about this in [our JavaScript overview page]([[docsref:/getting-started/javascript#data-attributes]]). + +Lastly, our styles build on the fundamental behaviors of common web elements. Whenever possible, we prefer to use what the browser provides. For example, you can put a `.btn` class on nearly any element, but most elements don’t provide any semantic value or browser functionality. So instead, we use ` + + `} /> + +## File input + + + + + +
      + + +
      +
      + + +
      +
      + + +
      +
      + + +
      `} /> + +## Color + +Set the `type="color"` and add `.form-control-color` to the ``. We use the modifier class to set fixed `height`s and override some inconsistencies between browsers. + +Color picker +`} /> + +## Datalists + +Datalists allow you to create a group of `

    Br%tI8Kfg4_&35i(R(62wqMKf%7IxH8kez2Q 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 z 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®rkC>2c08Yvh2bZ_Mx_&O~02 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 literal 0 HcmV?d00001 diff --git a/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/bootstrap-themes.png b/src/sampleWebAsWebApiClient/wwwroot/lib/bootstrap/site/src/assets/examples/heroes/bootstrap-themes.png new file mode 100644 index 0000000000000000000000000000000000000000..13c32337d6e18b84ff6a2dc191e022463a3e130b GIT binary patch literal 278159 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⁣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