diff --git a/.appbuilder-state.json b/.appbuilder-state.json
new file mode 100644
index 0000000..65f15a3
--- /dev/null
+++ b/.appbuilder-state.json
@@ -0,0 +1 @@
+{"applicationId":"fztemmkj4pbw","applicationName":"CRM App","platform":"WebComponents"}
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..59d9a3a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.ts]
+quote_type = single
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..15936f0
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,23 @@
+{
+ "root": true,
+ "env": {
+ "browser": true,
+ "es2021": true,
+ "jasmine": true
+ },
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 12,
+ "sourceType": "module"
+ },
+ "plugins": [
+ "@typescript-eslint"
+ ],
+ "rules": {
+ "@typescript-eslint/no-inferrable-types": "off"
+ }
+}
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
new file mode 100644
index 0000000..1c7359d
--- /dev/null
+++ b/.github/workflows/node.js.yml
@@ -0,0 +1,33 @@
+# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ node-version: [14.x, 16.x]
+ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v2
+ with:
+ node-version: ${{ matrix.node-version }}
+ # cache: 'npm' # enable after committing lock file from first install
+ - run: npm i # replace with 'npm ci' after committing lock file from first install
+# - run: npm run lint
+ - run: npm run build
+ - run: npm run test
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1a876d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/test
+
+# dependencies
+/node_modules
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# misc
+/coverage
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1c498fb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Romeo Rosete
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..75c878b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,29 @@
+# CRM App
+
+This project was generated with [App Builder Code Gen](https://www.infragistics.com/products/appbuilder).
+
+## Development server
+
+Run `npm start` to build the application, start a web server and open the application in the default browser. The application will open in `http://localhost:8000/` by default.
+
+## Build
+
+Run `npm run build` to build the application into an output directory.
+
+## Running unit tests
+
+Run `npm test` to execute the unit tests via [Web Test Runner](https://modern-web.dev/docs/test-runner/overview). Runs all `.test.ts` files under `./src` folder.
+
+## Running code style checks
+
+Run `npm run lint` to execute the code styling rules for the project.
+
+## Licensing
+
+See the [License FAQ and Installation documentation](https://www.infragistics.com/products/ignite-ui-web-components/web-components/components/general-licensing) for information on how to upgrade to the full licensed package, if the project is using a Trial version of Ignite UI for Web Components, and how to setup your environment and CI to use our licensed npm feed.
+
+Alternatively run `npm run infragistics-login` for a guided login to our licensed feed.
+
+## Additional resources
+
+- [Ignite UI for Web Components](https://www.infragistics.com/products/ignite-ui-web-components) - to learn more about the product or to dive into component specifics and showcases.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..034e848
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,21 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported |
+| ------- | ------------------ |
+| 5.1.x | :white_check_mark: |
+| 5.0.x | :x: |
+| 4.0.x | :white_check_mark: |
+| < 4.0 | :x: |
+
+## Reporting a Vulnerability
+
+Use this section to tell people how to report a vulnerability.
+
+Tell them where to go, how often they can expect to get an update on a
+reported vulnerability, what to expect if the vulnerability is accepted or
+declined, etc.
diff --git a/ig-theme.css b/ig-theme.css
new file mode 100644
index 0000000..35fa88f
--- /dev/null
+++ b/ig-theme.css
@@ -0,0 +1,273 @@
+:root {
+ --ig-font-family: "Lato";
+ --ig-primary-h: 209deg;
+ --ig-primary-s: 71%;
+ --ig-primary-l: 36%;
+ --ig-secondary-h: 209deg;
+ --ig-secondary-s: 70%;
+ --ig-secondary-l: 57%;
+ --ig-error-h: 347deg;
+ --ig-error-s: 51%;
+ --ig-error-l: 46%;
+ --ig-success-h: 98deg;
+ --ig-success-s: 50%;
+ --ig-success-l: 32%;
+ --ig-warn-h: 22deg;
+ --ig-warn-s: 81%;
+ --ig-warn-l: 52%;
+ --ig-info-h: 285deg;
+ --ig-info-s: 34%;
+ --ig-info-l: 33%;
+ --ig-primary-300-contrast: white;
+ --ig-primary-400-contrast: white;
+ --ig-primary-500-contrast: white;
+ --ig-primary-600-contrast: white;
+ --ig-primary-700-contrast: white;
+ --ig-primary-A200-contrast: white;
+ --ig-primary-A400-contrast: white;
+ --ig-secondary-600-contrast: black;
+ --ig-secondary-700-contrast: black;
+ --ig-secondary-A400-contrast: black;
+ --ig-error-400-contrast: white;
+ --ig-error-500-contrast: white;
+ --ig-error-600-contrast: white;
+ --ig-error-A200-contrast: white;
+ --ig-error-A400-contrast: white;
+ --ig-success-400-contrast: white;
+ --ig-success-500-contrast: white;
+ --ig-success-600-contrast: white;
+ --ig-success-700-contrast: white;
+ --ig-success-800-contrast: white;
+ --ig-success-A400-contrast: white;
+ --ig-warn-800-contrast: white;
+ --ig-warn-900-contrast: white;
+ --ig-warn-A700-contrast: white;
+ --ig-info-200-contrast: white;
+ --ig-info-300-contrast: white;
+ --ig-info-400-contrast: white;
+ --ig-info-500-contrast: white;
+ --ig-info-A100-contrast: white;
+ --ig-info-A200-contrast: white;
+}
+
+/* Charts */
+:root {
+ --charts-default-series: #9de772, #8b5bb1, #6db1ff, #9af2e4, #ee5879, #735656, #f7d262, #a8a8b7, #e051a9, #f8a15f;
+}
+igc-category-chart {
+ --brushes: var(--charts-default-series);
+ --outlines: var(--charts-default-series);
+ --marker-brushes: var(--charts-default-series);
+ --marker-outlines: var(--charts-default-series);
+ --negative-brushes: #ee5879;
+ --negative-outlines: #ee5879;
+ --title-text-color: hsla(var(--ig-gray-900));
+ --subtitle-text-color: hsla(var(--ig-gray-700));
+ --x-axis-label-text-color: hsla(var(--ig-gray-700));
+ --x-axis-title-text-color: hsla(var(--ig-gray-900));
+ --x-axis-stroke: hsla(var(--ig-gray-500));
+ --x-axis-tick-stroke: hsla(var(--ig-gray-500));
+ --y-axis-label-text-color: hsla(var(--ig-gray-700));
+ --y-axis-title-text-color: hsla(var(--ig-gray-900));
+ --y-axis-major-stroke: hsla(var(--ig-gray-300));
+ --y-axis-tick-stroke: hsla(var(--ig-gray-500));
+ --x-axis-label-text-style: normal 400 var(--ig-body-2-font-size) var(--ig-font-family);
+ --y-axis-label-text-style: normal 400 var(--ig-body-2-font-size) var(--ig-font-family);
+ --x-axis-title-text-style: normal 400 var(--ig-body-2-font-size) var(--ig-font-family);
+ --y-axis-title-text-style: normal 400 var(--ig-body-2-font-size) var(--ig-font-family);
+ --title-text-style: normal var(--ig-h6-font-weight) var(--ig-h6-font-size) var(--ig-font-family);
+ --subtitle-text-style: var(--ig-subtitle-1-font-weight) var(--ig-subtitle-1-font-size) var(--ig-font-family);
+}
+igc-pie-chart {
+ --brushes: var(--charts-default-series);
+ --outlines: var(--charts-default-series);
+ --label-extent: 30;
+ --label-outer-color: hsla(var(--ig-gray-700));
+ --text-style: normal 400 var(--ig-body-2-font-size) var(--ig-font-family);
+}
+
+/* Typography */
+h1 {
+ font-family: var(--ig-h1-font-family);
+ font-weight: var(--ig-h1-font-weight);
+ font-size: var(--ig-h1-font-size);
+ font-style: var(--ig-h1-font-style);
+ letter-spacing: var(--ig-h1-letter-spacing);
+ text-transform: var(--ig-h1-text-transform);
+ line-height: var(--ig-h1-line-height);
+ margin: 0;
+}
+
+h2 {
+ font-family: var(--ig-h2-font-family);
+ font-weight: var(--ig-h2-font-weight);
+ font-size: var(--ig-h2-font-size);
+ font-style: var(--ig-h2-font-style);
+ letter-spacing: var(--ig-h2-letter-spacing);
+ text-transform: var(--ig-h2-text-transform);
+ line-height: var(--ig-h2-line-height);
+ margin: 0;
+}
+
+h3 {
+ font-family: var(--ig-h3-font-family);
+ font-weight: var(--ig-h3-font-weight);
+ font-size: var(--ig-h3-font-size);
+ font-style: var(--ig-h3-font-style);
+ letter-spacing: var(--ig-h3-letter-spacing);
+ text-transform: var(--ig-h3-text-transform);
+ line-height: var(--ig-h3-line-height);
+ margin: 0;
+}
+
+h4 {
+ font-family: var(--ig-h4-font-family);
+ font-weight: var(--ig-h4-font-weight);
+ font-size: var(--ig-h4-font-size);
+ font-style: var(--ig-h4-font-style);
+ letter-spacing: var(--ig-h4-letter-spacing);
+ text-transform: var(--ig-h4-text-transform);
+ line-height: var(--ig-h4-line-height);
+ margin: 0;
+}
+
+h5 {
+ font-family: var(--ig-h5-font-family);
+ font-weight: var(--ig-h5-font-weight);
+ font-size: var(--ig-h5-font-size);
+ font-style: var(--ig-h5-font-style);
+ letter-spacing: var(--ig-h5-letter-spacing);
+ text-transform: var(--ig-h5-text-transform);
+ line-height: var(--ig-h5-line-height);
+ margin: 0;
+}
+
+h6 {
+ font-family: var(--ig-h6-font-family);
+ font-weight: var(--ig-h6-font-weight);
+ font-size: var(--ig-h6-font-size);
+ font-style: var(--ig-h6-font-style);
+ letter-spacing: var(--ig-h6-letter-spacing);
+ text-transform: var(--ig-h6-text-transform);
+ line-height: var(--ig-h6-line-height);
+ margin: 0;
+}
+
+p {
+ margin: 0;
+}
+
+img, video {
+ height: auto;
+ max-width: 100%;
+}
+
+.image_1 {
+ max-width: 100%;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+.h6,
+igc-card-header h1[slot='title'],
+igc-card-header h2[slot='title'],
+igc-card-header h3[slot='title'],
+igc-card-header h4[slot='title'],
+igc-card-header h5[slot='title'] {
+ font-family: var(--ig-h6-font-family);
+ font-weight: var(--ig-h6-font-weight);
+ font-size: var(--ig-h6-font-size);
+ font-style: var(--ig-h6-font-style);
+ letter-spacing: var(--ig-h6-letter-spacing);
+ text-transform: var(--ig-h6-text-transform);
+ line-height: var(--ig-h6-line-height);
+}
+
+.typography__body-1 {
+ font-family: var(--ig-body-1-font-family);
+ font-weight: var(--ig-body-1-font-weight);
+ font-size: var(--ig-body-1-font-size);
+ font-style: var(--ig-body-1-font-style);
+ letter-spacing: var(--ig-body-1-letter-spacing);
+ text-transform: var(--ig-body-1-text-transform);
+ line-height: var(--ig-body-1-line-height);
+}
+
+.typography__body-2 {
+ font-family: var(--ig-body-2-font-family);
+ font-weight: var(--ig-body-2-font-weight);
+ font-size: var(--ig-body-2-font-size);
+ font-style: var(--ig-body-2-font-style);
+ letter-spacing: var(--ig-body-2-letter-spacing);
+ text-transform: var(--ig-body-2-text-transform);
+ line-height: var(--ig-body-2-line-height);
+ margin: 0;
+}
+
+.typography__subtitle-1 {
+ font-family: var(--ig-subtitle-1-font-family);
+ font-weight: var(--ig-subtitle-1-font-weight);
+ font-size: var(--ig-subtitle-1-font-size);
+ font-style: var(--ig-subtitle-1-font-style);
+ letter-spacing: var(--ig-subtitle-1-letter-spacing);
+ text-transform: var(--ig-subtitle-1-text-transform);
+ line-height: var(--ig-subtitle-1-line-height);
+}
+
+.typography__subtitle-2,
+igc-card-header h1[slot='subtitle'],
+igc-card-header h2[slot='subtitle'],
+igc-card-header h3[slot='subtitle'],
+igc-card-header h4[slot='subtitle'],
+igc-card-header h5[slot='subtitle'],
+igc-card-header h6[slot='subtitle'] {
+ font-family: var(--ig-subtitle-2-font-family);
+ font-weight: var(--ig-subtitle-2-font-weight);
+ font-size: var(--ig-subtitle-2-font-size);
+ font-style: var(--ig-subtitle-2-font-style);
+ letter-spacing: var(--ig-subtitle-2-letter-spacing);
+ text-transform: var(--ig-subtitle-2-text-transform);
+ line-height: var(--ig-subtitle-2-line-height);
+ margin: 0;
+}
+
+.typography__caption {
+ font-family: var(--ig-caption-font-family);
+ font-weight: var(--ig-caption-font-weight);
+ font-size: var(--ig-caption-font-size);
+ font-style: var(--ig-caption-font-style);
+ letter-spacing: var(--ig-caption-letter-spacing);
+ text-transform: var(--ig-caption-text-transform);
+ line-height: var(--ig-caption-line-height);
+}
+
+.typography__overline {
+ font-family: var(--ig-overline-font-family);
+ font-weight: var(--ig-overline-font-weight);
+ font-size: var(--ig-overline-font-size);
+ font-style: var(--ig-overline-font-style);
+ letter-spacing: var(--ig-overline-letter-spacing);
+ text-transform: var(--ig-overline-text-transform);
+ line-height: var(--ig-overline-line-height);
+}
+
+
+/* align icons in their containers */
+.material-icons, .imx-icon {
+ vertical-align: middle;
+}
+
+.ig-typography h1,
+.ig-typography h2,
+.ig-typography h3,
+.ig-typography h4,
+.ig-typography h5,
+.ig-typography h6,
+.ig-typography p,
+.ig-typography__body-1 {
+ margin: 0 !important;
+}
diff --git a/ignite-ui-cli.json b/ignite-ui-cli.json
new file mode 100644
index 0000000..caa0c4b
--- /dev/null
+++ b/ignite-ui-cli.json
@@ -0,0 +1,16 @@
+{
+ "version": "13.1.5",
+ "project": {
+ "defaultPort": 8000,
+ "framework": "webcomponents",
+ "projectTemplate": "base",
+ "projectType": "igc-ts",
+ "theme": "default",
+ "isBundle": false,
+ "components": [],
+ "sourceFiles": [],
+ "isShowcase": false,
+ "version": ""
+ },
+ "build": {}
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..68b9a4d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ Ignite UI for Web Components
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..1f0e58d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "crmapp",
+ "version": "0.0.0",
+ "private": true,
+ "description": "WebComponents project for Ignite UI CLI",
+ "license": "MIT",
+ "author": "Infragistics",
+ "main": "dist/src/index.js",
+ "module": "dist/src/index.js",
+ "type": "module",
+ "exports": {
+ ".": "./dist/src/index.js",
+ "./crmapp.js": "./dist/src/crmapp.js"
+ },
+ "scripts": {
+ "start": "tsc && concurrently -k -r \"tsc --watch\" \"wds\"",
+ "build": "rimraf dist && tsc && node --max-old-space-size=4096 node_modules/rollup/dist/bin/rollup -c rollup.config.mjs",
+ "start:build": "web-dev-server --root-dir dist --app-index index.html --open",
+ "lint": "eslint \"**/*.{js,ts}\" --ignore-path .gitignore",
+ "test": "tsc --project tsconfig.test.json && wtr"
+ },
+ "dependencies": {
+ "@vaadin/router": "^1.7.4",
+ "igniteui-webcomponents": "~4.7.0",
+ "igniteui-webcomponents-charts": "~4.7.0",
+ "igniteui-webcomponents-core": "~4.7.0",
+ "igniteui-webcomponents-grids": "~4.7.0",
+ "igniteui-webcomponents-inputs": "~4.7.0",
+ "igniteui-webcomponents-layouts": "~4.7.0",
+ "lit": "^2.6.1",
+ "typescript": "^4.9.4"
+ },
+ "devDependencies": {
+ "@babel/preset-env": "^7.20.2",
+ "@open-wc/building-rollup": "^2.2.1",
+ "@open-wc/testing": "^3.1.7",
+ "@rollup/plugin-babel": "^6.0.3",
+ "@rollup/plugin-node-resolve": "^15.0.1",
+ "@typescript-eslint/eslint-plugin": "^5.49.0",
+ "@typescript-eslint/parser": "^5.49.0",
+ "@web/dev-server": "^0.1.35",
+ "@web/rollup-plugin-html": "^1.11.0",
+ "@web/rollup-plugin-import-meta-assets": "^1.0.7",
+ "@web/test-runner": "^0.15.0",
+ "babel-plugin-template-html-minifier": "^4.1.0",
+ "concurrently": "^7.6.0",
+ "deepmerge": "^4.2.2",
+ "eslint": "^8.32.0",
+ "eslint-plugin-lit": "^1.8.2",
+ "igniteui-cli": "^11.0.2",
+ "rimraf": "^4.1.2",
+ "rollup": "^2.79.0",
+ "rollup-plugin-copy-assets": "^2.0.3",
+ "rollup-plugin-terser": "^7.0.2",
+ "rollup-plugin-workbox": "^6.2.0",
+ "source-map": "^0.7.4",
+ "tslib": "^2.4.1"
+ }
+}
diff --git a/rollup.config.mjs b/rollup.config.mjs
new file mode 100644
index 0000000..47fb049
--- /dev/null
+++ b/rollup.config.mjs
@@ -0,0 +1,95 @@
+import babel from '@rollup/plugin-babel';
+import nodeResolve from '@rollup/plugin-node-resolve';
+import { rollupPluginHTML as html } from '@web/rollup-plugin-html';
+import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets';
+import path from 'path';
+import copy from 'rollup-plugin-copy-assets';
+import { terser } from 'rollup-plugin-terser';
+import { generateSW } from 'rollup-plugin-workbox';
+
+export default {
+ input: 'index.html',
+ output: {
+ entryFileNames: '[hash].js',
+ chunkFileNames: '[hash].js',
+ assetFileNames: '[hash][extname]',
+ format: 'es',
+ dir: 'dist',
+ },
+ onwarn: function(warning) {
+ // Skip https://rollupjs.org/troubleshooting/#error-this-is-undefined
+ if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
+ },
+ preserveEntrySignatures: false,
+
+ plugins: [
+ copy({
+ assets: [
+ 'src/assets',
+ ],
+ }),
+ /** Enable using HTML as rollup entrypoint */
+ html({
+ minify: true,
+ injectServiceWorker: true,
+ serviceWorkerPath: 'dist/sw.js',
+ }),
+ /** Resolve bare module imports */
+ nodeResolve(),
+ /** Minify JS */
+ terser(),
+ /** Bundle assets references via import.meta.url */
+ importMetaAssets(),
+ /** Compile JS to a lower language target */
+ babel({
+ compact: true,
+ babelHelpers: 'bundled',
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ targets: [
+ 'last 3 Chrome major versions',
+ 'last 3 Firefox major versions',
+ 'last 3 Edge major versions',
+ 'last 3 Safari major versions',
+ ],
+ modules: false,
+ bugfixes: true,
+ },
+ ],
+ ],
+ plugins: [
+ [
+ 'babel-plugin-template-html-minifier',
+ {
+ modules: { lit: ['html', { name: 'css', encapsulation: 'style' }] },
+ failOnError: false,
+ strictCSS: true,
+ htmlMinifier: {
+ collapseWhitespace: true,
+ conservativeCollapse: true,
+ removeComments: true,
+ caseSensitive: true,
+ minifyCSS: true,
+ },
+ },
+ ],
+ ],
+ }),
+ /** Create and inject a service worker */
+ generateSW({
+ globIgnores: ['polyfills/*.js', 'nomodule-*.js'],
+ navigateFallback: '/index.html',
+ // where to output the generated sw
+ swDest: path.join('dist', 'sw.js'),
+ // directory to match patterns against to be precached
+ globDirectory: path.join('dist'),
+ // cache any html js and css by default
+ globPatterns: ['**/*.{html,js,css,webmanifest}'],
+ skipWaiting: true,
+ clientsClaim: true,
+ runtimeCaching: [{ urlPattern: 'polyfills/*.js', handler: 'CacheFirst' }],
+ }),
+ ],
+};
diff --git a/src/app/account-sample/account-sample.test.ts b/src/app/account-sample/account-sample.test.ts
new file mode 100644
index 0000000..7c3587b
--- /dev/null
+++ b/src/app/account-sample/account-sample.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import AccountSample from './account-sample.js';
+
+describe('AccountSample', () => {
+ it(' is an instance of AccountSample', async () => {
+ const element = document.createElement('app-account-sample');
+ expect(element).to.be.instanceOf(AccountSample);
+ });
+});
diff --git a/src/app/account-sample/account-sample.ts b/src/app/account-sample/account-sample.ts
new file mode 100644
index 0000000..05ca50a
--- /dev/null
+++ b/src/app/account-sample/account-sample.ts
@@ -0,0 +1,871 @@
+import { html, css, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+import { defineComponents, IgcAccordionComponent, IgcAvatarComponent, IgcButtonComponent, IgcCheckboxComponent, IgcChipComponent, IgcExpansionPanelComponent, IgcIconComponent, IgcListComponent, IgcListItemComponent, IgcRippleComponent, IgcTabsComponent } from 'igniteui-webcomponents';
+
+defineComponents(IgcTabsComponent, IgcButtonComponent, IgcIconComponent, IgcRippleComponent, IgcAccordionComponent, IgcExpansionPanelComponent, IgcAvatarComponent, IgcCheckboxComponent, IgcListComponent, IgcListItemComponent, IgcChipComponent);
+
+@customElement('app-account-sample')
+export default class AccountSample extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .group {
+ border-color: hsla(var(--ig-gray-200));
+ border-width: 0px 0px 2px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: space-between;
+ position: relative;
+ padding: 20px;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .row-layout {
+ display: flex;
+ }
+ .account-header {
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: flex-start;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ }
+ .page-title {
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_1 {
+ background-color: rgba(71, 124, 41, 0.2);
+ border-radius: 6px;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ position: relative;
+ width: 48px;
+ height: 48px;
+ min-width: 48px;
+ min-height: 48px;
+ max-width: 48px;
+ max-height: 48px;
+ }
+ .group_2 {
+ justify-content: center;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_3 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_4 {
+ border-color: hsla(var(--ig-gray-200));
+ border-width: 0px 1px 0px 0px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ padding: 0 24px 0 0;
+ min-width: 50px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+ .group_5 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ min-width: 50px;
+ }
+ .group_6 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+ .group_7 {
+ background-color: hsla(var(--ig-gray-100));
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: stretch;
+ gap: 12px;
+ overflow: auto;
+ position: relative;
+ padding: 12px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .group_8 {
+ background-color: hsla(var(--ig-surface-500));
+ border-color: hsla(var(--ig-gray-200));
+ border-width: 1px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ padding: 16px;
+ min-width: 576px;
+ flex-grow: 2;
+ flex-basis: 0;
+ }
+ .tabs {
+ min-width: 0;
+ min-height: 0;
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+ .buttons-1 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ }
+ .accordion {
+ overflow-y: auto;
+ flex-shrink: 0;
+ }
+ .group_9 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 12px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_10 {
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 8px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_11 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 8px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_12 {
+ justify-content: flex-start;
+ align-items: baseline;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ }
+ .group_13 {
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ }
+ .demo-content {
+ border-color: hsla(var(--ig-secondary-200));
+ border-width: 2px;
+ border-style: dashed;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+ align-content: center;
+ gap: 32px;
+ padding: 48px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .demo-content-1 {
+ border-color: hsla(var(--ig-secondary-200));
+ border-width: 2px;
+ border-style: dashed;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+ align-content: center;
+ gap: 32px;
+ padding: 32px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .group_14 {
+ background-color: hsla(var(--ig-surface-500));
+ border-color: hsla(var(--ig-gray-200));
+ border-width: 1px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ padding: 16px;
+ min-width: max-content;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .group_15 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ padding: 24px 0 0;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .buttons {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ }
+ .group_16 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_17 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_18 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .image {
+ object-fit: cover;
+ width: 20px;
+ height: 20px;
+ min-width: 20px;
+ min-height: 0;
+ max-width: 20px;
+ max-height: 20px;
+ flex-shrink: 0;
+ }
+ .content {
+ height: max-content;
+ min-width: min-content;
+ }
+ .text {
+ color: hsla(var(--ig-gray-700));
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_1 {
+ color: hsla(var(--ig-primary-500));
+ height: max-content;
+ min-width: min-content;
+ }
+ .avatar::part(base) {
+ color: hsla(var(--ig-primary-500));
+ background-color: rgba(27, 95, 158, 0.2);
+ }
+ .hyperlink {
+ color: hsla(var(--ig-primary-500));
+ height: max-content;
+ min-width: min-content;
+ flex-shrink: 0;
+ }
+ .text_2 {
+ height: max-content;
+ min-width: 140px;
+ }
+ .hyperlink_1 {
+ color: hsla(var(--ig-info-500));
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_3 {
+ color: hsla(var(--ig-gray-600));
+ height: max-content;
+ min-width: min-content;
+ }
+ .image_1 {
+ object-fit: cover;
+ min-width: 0;
+ min-height: 0;
+ max-width: 160px;
+ flex-shrink: 0;
+ }
+ .text_4 {
+ text-align: center;
+ color: hsla(var(--ig-gray-500));
+ height: max-content;
+ min-width: min-content;
+ max-width: 320px;
+ }
+ .text_5 {
+ color: hsla(var(--ig-gray-800));
+ height: max-content;
+ min-width: min-content;
+ }
+ .chip {
+ width: max-content;
+ height: max-content;
+ }
+ .avatar_1::part(base) {
+ background-color: rgba(71, 124, 41, 0.2);
+ }
+ .avatar_2::part(base) {
+ color: hsla(var(--ig-gray-500));
+ }
+ .avatar_3::part(base) {
+ color: hsla(var(--ig-gray-500));
+ }
+ .avatar_4::part(base) {
+ background-color: transparent;
+ }
+ .avatar_5::part(base) {
+ background-color: transparent;
+ }
+ .avatar_6::part(base) {
+ background-color: transparent;
+ }
+ .tab-item-content {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ padding: 24px 0 0;
+ height: 100%;
+ min-width: 100%;
+ min-height: 50px;
+ max-height: 100%;
+ }
+ .tab-item-content_1 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ padding: 24px 0 0;
+ height: 100%;
+ min-width: 100%;
+ min-height: 50px;
+ max-height: 100%;
+ }
+ .tab-item-content_2 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ height: 100%;
+ min-width: 100%;
+ min-height: 50px;
+ max-height: 100%;
+ }
+ .tab-item-content_3 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ overflow: auto;
+ padding: 24px 0 0;
+ height: 100%;
+ min-width: 100%;
+ min-height: 50px;
+ max-height: 100%;
+ }
+ .button {
+ height: max-content;
+ flex-shrink: 0;
+ }
+ .checkbox {
+ width: max-content;
+ height: max-content;
+ }
+ .button::part(base) {
+ color: hsla(var(--ig-primary-500));
+ background-color: hsla(var(--ig-secondary-100));
+ }
+ .list {
+ height: max-content;
+ }
+ `;
+
+ render() {
+ return html`
+
+
+
+
+
+
+
+
+
+
+
+
+ person_add
+
+ Contact
+
+
+
+
+ star_border
+
+ New Opportunity
+
+
+
+
+ error_outline
+
+ New Case
+
+
+
+
+ note_add
+
+ Add note
+
+
+
+
+ file_copy
+
+ Add files
+
+
+
+
+
+
+
+
+
+
+ Account Name:
+
+
+ Thomas Hardy
+
+
+
+
+ Title:
+
+
+ Owner
+
+
+
+
+
+ Related Contacts (1)
+
+
+
+
+
+
+
+ Stage:
+
+
+ Qualification
+
+
+
+
+ Amount:
+
+
+ Owner
+
+
+
+
+ Close Date:
+
+
+ 9/12/2022
+
+
+
+
+ Opportunities (1)
+
+
+
+
+
+
+ insert_drive_file
+
+
+
+
+
+
+
+ insert_drive_file
+
+
+
+
+
+ Contracts (2)
+
+
+
+ No cases filed.
+
+ Cases (0)
+
+
+
+ No notes added.
+
+ Notes (0)
+
+
+
+ No files uploaded
+
+ Files (0)
+
+
+
+
+
+ info
+
+ Related
+
+
+
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+
+
+
+ info
+
+ Details
+
+
+
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+
+
+
+ info
+
+ News
+
+
+
+
+
+
+
+
+
+
+ calendar_today
+
+ New Meeting
+
+
+
+
+ assignment
+
+ New task
+
+
+
+
+ call
+
+ Log a call
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 11/1/2022
+
+
+ -
+
+
+ 10am
+
+
+
+ Zoom Meeting
+
+
+
+
+
+
+
+
+
+
+
+ 11/7/2022
+
+
+ -
+
+
+ 2pm
+
+
+
+ On Site Meeting
+
+
+
+
+
+
+
+
+
+
+
+ 11/14/2022
+
+
+ -
+
+
+ 4pm
+
+
+
+ Phone call
+
+
+
+
+
+ Upcoming Events (3)
+
+
+
+ No tasks added.
+
+ Tasks (0)
+
+
+
+ No call logged.
+
+ Call Logs (0)
+
+
+
+
+
+
+ info
+
+ Activity
+
+
+
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+
+
+
+ info
+
+ Conversations
+
+
+
+
+ `;
+ }
+}
diff --git a/src/app/accounts/accounts.test.ts b/src/app/accounts/accounts.test.ts
new file mode 100644
index 0000000..850d0ff
--- /dev/null
+++ b/src/app/accounts/accounts.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Accounts from './accounts.js';
+
+describe('Accounts', () => {
+ it(' is an instance of Accounts', async () => {
+ const element = document.createElement('app-accounts');
+ expect(element).to.be.instanceOf(Accounts);
+ });
+});
diff --git a/src/app/accounts/accounts.ts b/src/app/accounts/accounts.ts
new file mode 100644
index 0000000..dc1e555
--- /dev/null
+++ b/src/app/accounts/accounts.ts
@@ -0,0 +1,643 @@
+import { html, css, LitElement } from 'lit';
+import { customElement, state, query } from 'lit/decorators.js';
+import { Router } from '@vaadin/router';
+import { defineComponents, IgcButtonComponent, IgcDialogComponent, IgcDropdownComponent, IgcIconComponent, IgcInputComponent, IgcRippleComponent, IgcSelectComponent } from 'igniteui-webcomponents';
+import 'igniteui-webcomponents-grids/grids/combined.js';
+import { CustomersType } from '../models/northwind/customers-type';
+import { northwindService } from '../services/Northwind-service';
+
+defineComponents(IgcButtonComponent, IgcIconComponent, IgcRippleComponent, IgcSelectComponent, IgcInputComponent, IgcDropdownComponent, IgcDialogComponent);
+
+@customElement('app-accounts')
+export default class Accounts extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .row-layout {
+ display: flex;
+ }
+ .group {
+ background-color: hsla(var(--ig-gray-100));
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ overflow: auto;
+ position: relative;
+ padding: 12px;
+ min-width: 50px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .group_1 {
+ background-color: hsla(var(--ig-surface-500));
+ border-color: hsla(var(--ig-gray-300));
+ border-width: 1px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ padding: 16px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .group_2 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .header {
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ }
+ .page-title {
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 12px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_3 {
+ background-color: rgba(71, 124, 41, 0.2);
+ border-radius: 6px;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ position: relative;
+ width: 48px;
+ height: 48px;
+ min-width: 48px;
+ min-height: 48px;
+ max-width: 48px;
+ max-height: 48px;
+ }
+ .buttons {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ }
+ .filters-and-sorting {
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: flex-start;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_4 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 16px;
+ }
+ .group_5 {
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .group_6 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 24px;
+ position: relative;
+ padding: 16px 0 0;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_7 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 40px;
+ overflow: auto;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ max-height: 600px;
+ flex-shrink: 0;
+ }
+ .group_8 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .group_9 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: flex-start;
+ align-content: flex-start;
+ gap: 40px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_10 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 280px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .group_11 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ margin: 0 0 5px;
+ min-width: 50px;
+ }
+ .group_12 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: flex-start;
+ align-content: flex-start;
+ gap: 40px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .group_13 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .image {
+ object-fit: cover;
+ width: 20px;
+ height: 20px;
+ min-width: 20px;
+ min-height: 0;
+ max-width: 20px;
+ max-height: 20px;
+ flex-shrink: 0;
+ }
+ .h6 {
+ height: max-content;
+ min-width: min-content;
+ }
+ .icon {
+ --size: 24px;
+ font-size: 24px;
+ width: 24px;
+ height: 24px;
+ }
+ .h6_1 {
+ color: hsla(var(--ig-gray-900));
+ height: max-content;
+ }
+ .text {
+ margin: 0 0 24px;
+ height: max-content;
+ }
+ .text_1 {
+ color: hsla(var(--ig-gray-500));
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_2 {
+ color: hsla(var(--ig-gray-700));
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_3 {
+ margin: 0 0 8px;
+ height: max-content;
+ }
+ .textarea {
+ height: max-content;
+ }
+ .button {
+ height: max-content;
+ flex-shrink: 0;
+ }
+ .select {
+ height: max-content;
+ min-width: min-content;
+ flex-shrink: 0;
+ }
+ .input {
+ height: max-content;
+ min-width: 120px;
+ flex-shrink: 0;
+ }
+ .dropdown {
+ min-width: min-content;
+ }
+ .user-input {
+ height: max-content;
+ }
+ .user-input_2 {
+ height: max-content;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .button_1 {
+ margin: 8px 16px 16px 0;
+ height: max-content;
+ }
+ .button_2::part(base) {
+ color: hsla(var(--ig-primary-500));
+ background-color: hsla(var(--ig-secondary-100));
+ }
+ .button_3::part(base) {
+ color: hsla(var(--ig-primary-500));
+ background-color: hsla(var(--ig-secondary-100));
+ }
+ .button_4::part(base) {
+ color: hsla(var(--ig-primary-500));
+ background-color: hsla(var(--ig-secondary-100));
+ }
+ .button_5::part(base) {
+ color: hsla(var(--ig-primary-500));
+ }
+ .dropdown::part(base) {
+ height: max-content;
+ }
+ .button_1_1::part(base) {
+ color: hsla(var(--ig-surface-500));
+ }
+ .grid {
+ min-height: 0;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ `;
+
+ constructor() {
+ super();
+ this.northwindCustomers = northwindService.getData('CustomersType');
+ }
+
+ @state()
+ private value: string = '2';
+
+ @query('#button')
+ private button?: IgcButtonComponent;
+
+ @query('#dropdown')
+ private dropdown?: IgcDropdownComponent;
+
+ @state()
+ private northwindCustomers: CustomersType[] = [];
+
+ @query('#new-account-dialog')
+ private newAccountDialog?: IgcDialogComponent;
+
+ @state()
+ private value1: string = '1';
+
+ render() {
+ return html`
+
+
+
+
+
+
+
+
+
+ this.value = e.detail.value}" class="select">
+
+ My Accounts
+
+
+ All Accounts
+
+
+
+
+
+ search
+
+
+
+
+
+ this.dropdown?.toggle(this.button)}" id="button" class="button button_5">
+ Recently Updated
+
+ keyboard_arrow_down
+
+
+
+
+
+ Name
+
+
+ Recently Updated
+
+
+
+
+
+
Router.go('/account-sample')}" class="ig-typography ig-scrollbar grid">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ New Account
+
+
+
+
+ ACCOUNT INFORMATION
+
+
+
+
+
+
+ search
+
+
+
+ this.value1 = e.detail.value}" class="user-input">
+
+ -- None --
+
+
+ Analyst
+
+
+ Competitor
+
+
+ Customer
+
+
+ Integrator
+
+
+ Investor
+
+
+ Partner
+
+
+ Press
+
+
+ Prospect
+
+
+ Reseller
+
+
+ Other
+
+
+
+ Textarea not yet available in WebComponents
+
+
+
+
+ Account Owner
+
+
+ Andrea Silveira
+
+
+
+
+
+ search
+
+
+
+
+
this.value1 = e.detail.value}" class="user-input">
+
+ -- None --
+
+
+ Agriculture
+
+
+ Apparel
+
+
+ Banking
+
+
+ Biotechnology
+
+
+ Chemicals
+
+
+ Communications
+
+
+ Construction
+
+
+
+
+ Self Employed
+
+
+ 1-10
+
+
+ 11-50
+
+
+ 51-250
+
+
+ +250
+
+
+
+
+
+
+
+
+ BILLING INFORMATION
+
+
+
+
+ search
+
+
+
+
+
+
+
+
+
+
+ this.value1 = e.detail.value}" class="user-input_2">
+
+ Country 1
+
+
+ Country 1
+
+
+ Country 1
+
+
+ Country 1
+
+
+ Country 1
+
+
+
+
+
+
+ SHIPPING INFORMATION
+
+
+
+
+ search
+
+
+
+
+
+
+
+
+
+
+ this.value1 = e.detail.value}" class="user-input_2">
+
+ Country 1
+
+
+ Country 1
+
+
+ Country 1
+
+
+ Country 1
+
+
+ Country 1
+
+
+
+
+
+
+
+
+ this.newAccountDialog?.toggle()}" class="button_1">
+ Cancel
+
+
+ this.newAccountDialog?.toggle()}" class="button_1 button_1_1">
+ Save
+
+
+
+
+ `;
+ }
+}
diff --git a/src/app/app-routing.ts b/src/app/app-routing.ts
new file mode 100644
index 0000000..f3fabe6
--- /dev/null
+++ b/src/app/app-routing.ts
@@ -0,0 +1,24 @@
+import { Route } from '@vaadin/router';
+import './not-found/not-found.js';
+import './home/home';
+import './accounts/accounts';
+import './account-sample/account-sample';
+import './contacts/contacts';
+import './contracts/contracts';
+import './reports/reports';
+import './calendar/calendar';
+import './tasks/tasks';
+
+export const routes: Route[] = [
+ { path: '', component: 'app-home', name: 'Home' },
+ { path: 'home', component: 'app-home', name: 'Home' },
+ { path: 'accounts', component: 'app-accounts', name: 'Accounts' },
+ { path: 'account-sample', component: 'app-account-sample', name: 'Account Sample' },
+ { path: 'contacts', component: 'app-contacts', name: 'Contacts' },
+ { path: 'contracts', component: 'app-contracts', name: 'Contracts' },
+ { path: 'reports', component: 'app-reports', name: 'Reports' },
+ { path: 'calendar', component: 'app-calendar', name: 'Calendar' },
+ { path: 'tasks', component: 'app-tasks', name: 'Tasks' },
+ // The fallback route should always be after other alternatives.
+ { path: '(.*)', component: 'app-not-found' }
+];
diff --git a/src/app/app.ts b/src/app/app.ts
new file mode 100644
index 0000000..e9750b0
--- /dev/null
+++ b/src/app/app.ts
@@ -0,0 +1,204 @@
+import { html, css, LitElement } from 'lit';
+import { customElement, state, query } from 'lit/decorators.js';
+import { Router } from '@vaadin/router';
+import { routes } from './app-routing.js';
+import { defineComponents, IgcAvatarComponent, IgcIconButtonComponent, IgcIconComponent, IgcListComponent, IgcListItemComponent, IgcNavbarComponent, IgcNavDrawerComponent, IgcRippleComponent } from 'igniteui-webcomponents';
+import { Table1Type } from './models/crmapp-data/table1-type';
+import { cRMAppDataService } from './services/CRMAppData-service';
+
+defineComponents(IgcIconComponent, IgcNavbarComponent, IgcIconButtonComponent, IgcRippleComponent, IgcNavDrawerComponent, IgcListComponent, IgcListItemComponent, IgcAvatarComponent);
+
+@customElement('app-root')
+export default class App extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .row-layout {
+ display: flex;
+ }
+ .group {
+ background-color: hsla(var(--ig-gray-900));
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ overflow: hidden;
+ position: relative;
+ min-height: 56px;
+ }
+ .group_1 {
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ position: relative;
+ width: 56px;
+ height: 56px;
+ min-width: 50px;
+ min-height: 50px;
+ max-width: 56px;
+ max-height: 56px;
+ }
+ .group_2 {
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 1rem;
+ overflow: hidden;
+ }
+ .group_3 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ min-height: 50px;
+ flex-grow: 1;
+ }
+ .icon {
+ --size: 24px;
+ font-size: 24px;
+ width: 24px;
+ height: 24px;
+ color: hsla(var(--ig-surface-500));
+ }
+ .image {
+ object-fit: none;
+ width: 413px;
+ height: 14px;
+ min-width: 413px;
+ min-height: 14px;
+ max-width: 413px;
+ max-height: 14px;
+ flex-shrink: 0;
+ }
+ .avatar::part(base) {
+ background-color: transparent;
+ }
+ .icon-button::part(base) {
+ color: hsla(var(--ig-surface-500));
+ }
+ .navbar {
+ color: hsla(var(--ig-surface-500));
+ background-color: hsla(var(--ig-primary-500));
+ height: max-content;
+ min-width: min-content;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .nav-drawer {
+ min-width: min-content;
+ min-height: 0;
+ max-width: 200px;
+ flex-shrink: 0;
+ }
+ .view-container {
+ overflow: auto;
+ display: block;
+ position: relative;
+ flex-grow: 1;
+ }
+ .nav-drawer::part(main) {
+ width: 200px;
+ }
+ .list {
+ height: max-content;
+ }
+ `;
+
+ constructor() {
+ super();
+ cRMAppDataService.getTable1List().then((data) => {
+ this.cRMAppDataTable1 = data;
+ }, err => console.log(err));
+ }
+
+ @query('#nav-drawer')
+ private navDrawer?: IgcNavDrawerComponent;
+
+ @state()
+ private cRMAppDataTable1: Table1Type[] = [];
+
+ render() {
+ return html`
+
+
+
+
this.navDrawer?.toggle()}" class="row-layout group_1">
+
+ menu
+
+
+
+
+
+
+
+
+ search
+
+
+
+
+
+ settings
+
+
+
+
+
+ notifications_none
+
+
+
+
+
+
+
+
+ ${this.cRMAppDataTable1?.map((item) => html`
+ Router.go('/home')}">
+
+ Home
+
+ `)}
+ Router.go('/accounts')}">
+
+ Accounts
+
+ Router.go('/contacts')}">
+
+ Contacts
+
+ Router.go('/contracts')}">
+
+ Contracts
+
+ Router.go('/reports')}">
+
+ Reports
+
+ Router.go('/calendar')}">
+
+ Calendar
+
+ Router.go('/tasks')}">
+
+ Tasks
+
+
+
+
+
+ `;
+ }
+
+ firstUpdated() {
+ const outlet = this.shadowRoot?.querySelector('router-outlet');
+ const router = new Router(outlet);
+ router.setRoutes(routes);
+ }
+}
diff --git a/src/app/calendar/calendar.test.ts b/src/app/calendar/calendar.test.ts
new file mode 100644
index 0000000..6156e30
--- /dev/null
+++ b/src/app/calendar/calendar.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Calendar from './calendar.js';
+
+describe('Calendar', () => {
+ it(' is an instance of Calendar', async () => {
+ const element = document.createElement('app-calendar');
+ expect(element).to.be.instanceOf(Calendar);
+ });
+});
diff --git a/src/app/calendar/calendar.ts b/src/app/calendar/calendar.ts
new file mode 100644
index 0000000..183adf3
--- /dev/null
+++ b/src/app/calendar/calendar.ts
@@ -0,0 +1,72 @@
+import { html, css, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('app-calendar')
+export default class Calendar extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .demo-content {
+ background-color: transparent;
+ border-color: hsla(var(--ig-gray-400));
+ border-width: 2px;
+ border-style: dashed;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ position: absolute;
+ padding: 64px;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .image {
+ object-fit: cover;
+ margin: 0 0 24px;
+ min-width: 0;
+ min-height: 0;
+ max-width: 280px;
+ flex-shrink: 0;
+ }
+ .h5 {
+ color: hsla(var(--ig-secondary-800));
+ margin: 0 0 16px;
+ height: max-content;
+ min-width: min-content;
+ }
+ .text {
+ text-align: center;
+ color: hsla(var(--ig-gray-700));
+ margin: 0 0 24px;
+ height: max-content;
+ min-width: min-content;
+ max-width: 320px;
+ }
+ `;
+
+ render() {
+ return html`
+
+
+
+
+ Start building!
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+ `;
+ }
+}
diff --git a/src/app/contacts/contacts.test.ts b/src/app/contacts/contacts.test.ts
new file mode 100644
index 0000000..c69aff8
--- /dev/null
+++ b/src/app/contacts/contacts.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Contacts from './contacts.js';
+
+describe('Contacts', () => {
+ it(' is an instance of Contacts', async () => {
+ const element = document.createElement('app-contacts');
+ expect(element).to.be.instanceOf(Contacts);
+ });
+});
diff --git a/src/app/contacts/contacts.ts b/src/app/contacts/contacts.ts
new file mode 100644
index 0000000..ee005f8
--- /dev/null
+++ b/src/app/contacts/contacts.ts
@@ -0,0 +1,72 @@
+import { html, css, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('app-contacts')
+export default class Contacts extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .demo-content {
+ background-color: transparent;
+ border-color: hsla(var(--ig-gray-400));
+ border-width: 2px;
+ border-style: dashed;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ position: absolute;
+ padding: 64px;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .image {
+ object-fit: cover;
+ margin: 0 0 24px;
+ min-width: 0;
+ min-height: 0;
+ max-width: 280px;
+ flex-shrink: 0;
+ }
+ .h5 {
+ color: hsla(var(--ig-secondary-800));
+ margin: 0 0 16px;
+ height: max-content;
+ min-width: min-content;
+ }
+ .text {
+ text-align: center;
+ color: hsla(var(--ig-gray-700));
+ margin: 0 0 24px;
+ height: max-content;
+ min-width: min-content;
+ max-width: 320px;
+ }
+ `;
+
+ render() {
+ return html`
+
+
+
+
+ Start building!
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+ `;
+ }
+}
diff --git a/src/app/contracts/contracts.test.ts b/src/app/contracts/contracts.test.ts
new file mode 100644
index 0000000..dbd596f
--- /dev/null
+++ b/src/app/contracts/contracts.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Contracts from './contracts.js';
+
+describe('Contracts', () => {
+ it(' is an instance of Contracts', async () => {
+ const element = document.createElement('app-contracts');
+ expect(element).to.be.instanceOf(Contracts);
+ });
+});
diff --git a/src/app/contracts/contracts.ts b/src/app/contracts/contracts.ts
new file mode 100644
index 0000000..345489b
--- /dev/null
+++ b/src/app/contracts/contracts.ts
@@ -0,0 +1,72 @@
+import { html, css, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('app-contracts')
+export default class Contracts extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .demo-content {
+ background-color: transparent;
+ border-color: hsla(var(--ig-gray-400));
+ border-width: 2px;
+ border-style: dashed;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ position: absolute;
+ padding: 64px;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .image {
+ object-fit: cover;
+ margin: 0 0 24px;
+ min-width: 0;
+ min-height: 0;
+ max-width: 280px;
+ flex-shrink: 0;
+ }
+ .h5 {
+ color: hsla(var(--ig-secondary-800));
+ margin: 0 0 16px;
+ height: max-content;
+ min-width: min-content;
+ }
+ .text {
+ text-align: center;
+ color: hsla(var(--ig-gray-700));
+ margin: 0 0 24px;
+ height: max-content;
+ min-width: min-content;
+ max-width: 320px;
+ }
+ `;
+
+ render() {
+ return html`
+
+
+
+
+ Start building!
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+ `;
+ }
+}
diff --git a/src/app/home/home.test.ts b/src/app/home/home.test.ts
new file mode 100644
index 0000000..abc508b
--- /dev/null
+++ b/src/app/home/home.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Home from './home.js';
+
+describe('Home', () => {
+ it(' is an instance of Home', async () => {
+ const element = document.createElement('app-home');
+ expect(element).to.be.instanceOf(Home);
+ });
+});
diff --git a/src/app/home/home.ts b/src/app/home/home.ts
new file mode 100644
index 0000000..d2c9246
--- /dev/null
+++ b/src/app/home/home.ts
@@ -0,0 +1,498 @@
+import { html, css, LitElement } from 'lit';
+import { customElement, state } from 'lit/decorators.js';
+import { Router } from '@vaadin/router';
+import { defineComponents, IgcAvatarComponent, IgcChipComponent, IgcListComponent, IgcListItemComponent } from 'igniteui-webcomponents';
+import { IgcCategoryChartModule } from 'igniteui-webcomponents-charts';
+import { ModuleManager } from 'igniteui-webcomponents-core';
+import 'igniteui-webcomponents-grids/grids/combined.js';
+import { CustomersType } from '../models/northwind/customers-type';
+import { MeetingsTasksType } from '../models/crmapp-data/meetings-tasks-type';
+import { RevenueType } from '../models/e-commerce/revenue-type';
+import { eCommerceService } from '../services/ECommerce-service';
+import { cRMAppDataService } from '../services/CRMAppData-service';
+import { northwindService } from '../services/Northwind-service';
+
+ModuleManager.register(IgcCategoryChartModule);
+
+defineComponents(IgcListComponent, IgcListItemComponent, IgcAvatarComponent, IgcChipComponent);
+
+@customElement('app-home')
+export default class Home extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .row-layout {
+ display: flex;
+ }
+ .group {
+ background-color: hsla(var(--ig-gray-100));
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 12px;
+ overflow: auto;
+ position: relative;
+ padding: 12px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .group_1 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 12px;
+ position: relative;
+ min-width: 280px;
+ min-height: 50px;
+ flex-grow: 2;
+ flex-basis: 0;
+ }
+ .group_2 {
+ background-color: hsla(var(--ig-surface-500));
+ border-color: hsla(var(--ig-gray-200));
+ border-width: 1px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ padding: 16px 16px 24px;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .group_3 {
+ background-color: hsla(var(--ig-surface-500));
+ border-color: hsla(var(--ig-gray-300));
+ border-width: 1px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 16px;
+ position: relative;
+ padding: 16px 16px 24px;
+ min-width: 50px;
+ min-height: 50px;
+ flex-shrink: 0;
+ }
+ .group_4 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 12px;
+ position: relative;
+ min-width: 280px;
+ min-height: 50px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .group_5 {
+ background-color: hsla(var(--ig-surface-500));
+ border-color: hsla(var(--ig-gray-300));
+ border-width: 1px;
+ border-style: solid;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 16px;
+ overflow: auto;
+ position: relative;
+ padding: 16px 16px 24px;
+ min-width: 50px;
+ max-height: 428px;
+ flex-shrink: 0;
+ }
+ .group_6 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ overflow: auto;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_7 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .group_8 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_9 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: flex-start;
+ gap: 4px;
+ position: relative;
+ flex-shrink: 0;
+ }
+ .group_10 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_11 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_12 {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: -2px;
+ position: relative;
+ min-width: 50px;
+ flex-shrink: 0;
+ }
+ .group_13 {
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ gap: 2px;
+ position: relative;
+ min-width: 50px;
+ }
+ .text {
+ height: max-content;
+ min-width: min-content;
+ }
+ .hyperlink {
+ text-align: right;
+ color: hsla(var(--ig-primary-500));
+ cursor: pointer;
+ height: max-content;
+ min-width: min-content;
+ }
+ .avatar::part(base) {
+ background-color: rgba(71, 124, 41, 0.2);
+ }
+ .hyperlink_1 {
+ color: hsla(var(--ig-primary-500));
+ cursor: pointer;
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_1 {
+ color: hsla(var(--ig-gray-800));
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_2 {
+ color: hsla(var(--ig-gray-600));
+ height: max-content;
+ min-width: min-content;
+ }
+ .text_3 {
+ color: hsla(var(--ig-gray-600));
+ margin: 0 4px 0 0;
+ height: max-content;
+ min-width: min-content;
+ }
+ .hyperlink_2 {
+ color: hsla(var(--ig-primary-500));
+ height: max-content;
+ min-width: min-content;
+ }
+ .hyperlink_3 {
+ color: hsla(var(--ig-gray-600));
+ height: max-content;
+ min-width: min-content;
+ flex-shrink: 0;
+ }
+ .chip {
+ margin: 4px 0 0;
+ width: max-content;
+ height: max-content;
+ }
+ .avatar_1::part(base) {
+ background-color: rgba(27, 95, 158, 0.2);
+ }
+ .avatar_2::part(base) {
+ background-color: transparent;
+ }
+ .avatar_3::part(base) {
+ background-color: transparent;
+ }
+ .category-chart {
+ --brushes: #72B24D #9362A3 #F06583 #FCB13F #407DB7;
+ --outlines: #72B24D #9362A3 #F06583 #FCB13F #407DB7;
+ --marker-brushes: #72B24D #9362A3 #F06583 #FCB13F #407DB7;
+ --marker-outlines: #72B24D #9362A3 #F06583 #FCB13F #407DB7;
+ min-height: 300px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .grid {
+ min-width: 248px;
+ min-height: 300px;
+ flex-grow: 1;
+ flex-basis: 0;
+ }
+ .list {
+ height: max-content;
+ }
+ `;
+
+ constructor() {
+ super();
+ eCommerceService.getRevenueList().then((data) => {
+ this.eCommerceRevenue = data;
+ }, err => console.log(err));
+ this.northwindCustomers = northwindService.getData('CustomersType');
+ cRMAppDataService.getMeetingsTasksList().then((data) => {
+ this.cRMAppDataMeetingsTasks = data;
+ }, err => console.log(err));
+ }
+
+ @state()
+ private eCommerceRevenue: RevenueType[] = [];
+
+ @state()
+ private northwindCustomers: CustomersType[] = [];
+
+ @state()
+ private cRMAppDataMeetingsTasks: MeetingsTasksType[] = [];
+
+ render() {
+ return html`
+
+
+
+ `;
+ }
+}
diff --git a/src/app/models/crmapp-data/meetings-tasks-type.ts b/src/app/models/crmapp-data/meetings-tasks-type.ts
new file mode 100644
index 0000000..32cbcaa
--- /dev/null
+++ b/src/app/models/crmapp-data/meetings-tasks-type.ts
@@ -0,0 +1,10 @@
+export interface MeetingsTasksType {
+ MeetingDate: string;
+ MeetingTime: string;
+ Contact: string;
+ Company: string;
+ MeetingType: string;
+ Task: string;
+ TaskStatus: string;
+ DueDate: string;
+}
diff --git a/src/app/models/crmapp-data/table1-type.ts b/src/app/models/crmapp-data/table1-type.ts
new file mode 100644
index 0000000..657baff
--- /dev/null
+++ b/src/app/models/crmapp-data/table1-type.ts
@@ -0,0 +1,6 @@
+export interface Table1Type {
+ Client: string;
+ Contact: string;
+ Address: string;
+ Phone: string;
+}
diff --git a/src/app/models/e-commerce/revenue-type.ts b/src/app/models/e-commerce/revenue-type.ts
new file mode 100644
index 0000000..eb05b36
--- /dev/null
+++ b/src/app/models/e-commerce/revenue-type.ts
@@ -0,0 +1,4 @@
+export interface RevenueType {
+ Month: string;
+ Revenue: number;
+}
diff --git a/src/app/models/northwind/address-type.ts b/src/app/models/northwind/address-type.ts
new file mode 100644
index 0000000..49db6cd
--- /dev/null
+++ b/src/app/models/northwind/address-type.ts
@@ -0,0 +1,8 @@
+export interface AddressType {
+ street: string;
+ city: string;
+ region: string;
+ postalCode: string;
+ country: string;
+ phone: string;
+}
diff --git a/src/app/models/northwind/customers-type.ts b/src/app/models/northwind/customers-type.ts
new file mode 100644
index 0000000..b59f0fe
--- /dev/null
+++ b/src/app/models/northwind/customers-type.ts
@@ -0,0 +1,9 @@
+import { AddressType } from './address-type';
+
+export interface CustomersType {
+ customerID: string;
+ companyName: string;
+ contactName: string;
+ contactTitle: string;
+ address: AddressType;
+}
diff --git a/src/app/not-found/not-found.ts b/src/app/not-found/not-found.ts
new file mode 100644
index 0000000..f2d99f4
--- /dev/null
+++ b/src/app/not-found/not-found.ts
@@ -0,0 +1,11 @@
+import { html, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('app-not-found')
+export default class NotFound extends LitElement {
+ render() {
+ return html`
+ Error 404: Page not found
+ `;
+ }
+}
diff --git a/src/app/reports/reports.test.ts b/src/app/reports/reports.test.ts
new file mode 100644
index 0000000..cdca1da
--- /dev/null
+++ b/src/app/reports/reports.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Reports from './reports.js';
+
+describe('Reports', () => {
+ it(' is an instance of Reports', async () => {
+ const element = document.createElement('app-reports');
+ expect(element).to.be.instanceOf(Reports);
+ });
+});
diff --git a/src/app/reports/reports.ts b/src/app/reports/reports.ts
new file mode 100644
index 0000000..397efdc
--- /dev/null
+++ b/src/app/reports/reports.ts
@@ -0,0 +1,72 @@
+import { html, css, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('app-reports')
+export default class Reports extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .demo-content {
+ background-color: transparent;
+ border-color: hsla(var(--ig-gray-400));
+ border-width: 2px;
+ border-style: dashed;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ position: absolute;
+ padding: 64px;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .image {
+ object-fit: cover;
+ margin: 0 0 24px;
+ min-width: 0;
+ min-height: 0;
+ max-width: 280px;
+ flex-shrink: 0;
+ }
+ .h5 {
+ color: hsla(var(--ig-secondary-800));
+ margin: 0 0 16px;
+ height: max-content;
+ min-width: min-content;
+ }
+ .text {
+ text-align: center;
+ color: hsla(var(--ig-gray-700));
+ margin: 0 0 24px;
+ height: max-content;
+ min-width: min-content;
+ max-width: 320px;
+ }
+ `;
+
+ render() {
+ return html`
+
+
+
+
+ Start building!
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+ `;
+ }
+}
diff --git a/src/app/services/CRMAppData-service.ts b/src/app/services/CRMAppData-service.ts
new file mode 100644
index 0000000..3bc2ed8
--- /dev/null
+++ b/src/app/services/CRMAppData-service.ts
@@ -0,0 +1,21 @@
+import { Table1Type } from '../models/crmapp-data/table1-type';
+import { MeetingsTasksType } from '../models/crmapp-data/meetings-tasks-type';
+
+class CRMAppDataService {
+ public getTable1List = async (): Promise => {
+ const response = await fetch('https://excel2json.io/api/share/7c450fc9-b631-4529-e668-08dab79fa5b4');
+ if (!response.ok) {
+ return Promise.resolve([]);
+ }
+ return response.json();
+ }
+
+ public getMeetingsTasksList = async (): Promise => {
+ const response = await fetch('https://excel2json.io/api/share/2fd4ecd6-da6c-4e37-e666-08dab79fa5b4');
+ if (!response.ok) {
+ return Promise.resolve([]);
+ }
+ return response.json();
+ }
+}
+export const cRMAppDataService: CRMAppDataService = new CRMAppDataService();
diff --git a/src/app/services/ECommerce-service.ts b/src/app/services/ECommerce-service.ts
new file mode 100644
index 0000000..eef552c
--- /dev/null
+++ b/src/app/services/ECommerce-service.ts
@@ -0,0 +1,12 @@
+import { RevenueType } from '../models/e-commerce/revenue-type';
+
+class ECommerceService {
+ public getRevenueList = async (): Promise => {
+ const response = await fetch('https://excel2json.io/api/share/03e74dde-d2e1-4fee-437d-08da496bf5f2');
+ if (!response.ok) {
+ return Promise.resolve([]);
+ }
+ return response.json();
+ }
+}
+export const eCommerceService: ECommerceService = new ECommerceService();
diff --git a/src/app/services/Northwind-service.ts b/src/app/services/Northwind-service.ts
new file mode 100644
index 0000000..b96914b
--- /dev/null
+++ b/src/app/services/Northwind-service.ts
@@ -0,0 +1,8 @@
+import { Northwind } from '../static-data/northwind';
+
+class NorthwindService {
+ public getData(tableName: string): any[] {
+ return Northwind[tableName];
+ }
+}
+export const northwindService: NorthwindService = new NorthwindService();
diff --git a/src/app/static-data/northwind.ts b/src/app/static-data/northwind.ts
new file mode 100644
index 0000000..421f641
--- /dev/null
+++ b/src/app/static-data/northwind.ts
@@ -0,0 +1,4 @@
+/* eslint-disable */
+export const Northwind: { [key: string]: any } = {
+ 'CustomersType': [{"customerID":"AROUT","companyName":"Around the Horn","contactName":"Thomas Hardy","contactTitle":"Sales Representative","address":{"street":"120 Hanover Sq.","city":"London","region":null,"postalCode":"WA1 1DP","country":"UK","phone":"(171) 555-7788"}},{"customerID":"BERGS","companyName":"Berglunds snabbköp","contactName":"Christina Berglund","contactTitle":"Order Administrator","address":{"street":"Berguvsvägen 8","city":"LuleÃ¥","region":null,"postalCode":"S-958 22","country":"Sweden","phone":"0921-12 34 65"}},{"customerID":"BLAUS","companyName":"Blauer See Delikatessen","contactName":"Hanna Moos","contactTitle":"Sales Representative","address":{"street":"Forsterstr. 57","city":"Mannheim","region":null,"postalCode":"68306","country":"Germany","phone":"0621-08460"}},{"customerID":"BLONP","companyName":"Blondesddsl père et fils","contactName":"Frédérique Citeaux","contactTitle":"Marketing Manager","address":{"street":"24 place Kléber","city":"Strasbourg","region":null,"postalCode":"67000","country":"France","phone":"88.60.15.31"}},{"customerID":"BOLID","companyName":"Bólido Comidas preparadas","contactName":"MartÃn Sommer","contactTitle":"Owner","address":{"street":"67C Araquil","city":"Madrid","region":null,"postalCode":"28023","country":"Spain","phone":"(91) 555 22 82"}},{"customerID":"BONAP","companyName":"Bon app'","contactName":"Laurence Lebihan","contactTitle":"Owner","address":{"street":"12 rue des Bouchers","city":"Marseille","region":null,"postalCode":"13008","country":"France","phone":"91.24.45.40"}},{"customerID":"ANTON","companyName":"Antonio Moreno TaquerÃa","contactName":"Antonio Moreno","contactTitle":"Owner","address":{"street":"Mataderos 2312","city":"México D.F.","region":null,"postalCode":"5023","country":"Mexico","phone":"(5) 555-3932"}},{"customerID":"ANATR","companyName":"Ana Trujillo Emparedados y helados","contactName":"Ana Trujillo","contactTitle":"Owner","address":{"street":"Avda. de la Constitución 2222","city":"México D.F.","region":null,"postalCode":"5021","country":"Mexico","phone":"(5) 555-4729"}},{"customerID":"CACTU","companyName":"Cactus Comidas para llevar","contactName":"Patricio Simpson","contactTitle":"Sales Agent","address":{"street":"Cerrito 333","city":"Buenos Aires","region":null,"postalCode":"1010","country":"Argentina","phone":"(1) 135-5555"}},{"customerID":"BSBEV","companyName":"B's Beverages","contactName":"Victoria Ashworth","contactTitle":"Sales Representative","address":{"street":"Fauntleroy Circus","city":"London","region":null,"postalCode":"EC2 5NT","country":"UK","phone":"(171) 555-1212"}},{"customerID":"CENTC","companyName":"Centro comercial Moctezuma","contactName":"Francisco Chang","contactTitle":"Marketing Manager","address":{"street":"Sierras de Granada 9993","city":"México D.F.","region":null,"postalCode":"5022","country":"Mexico","phone":"(5) 555-3392"}},{"customerID":"CHOPS","companyName":"Chop-suey Chinese","contactName":"Yang Wang","contactTitle":"Owner","address":{"street":"Hauptstr. 29","city":"Bern","region":null,"postalCode":"3012","country":"Switzerland","phone":"0452-076545"}},{"customerID":"COMMI","companyName":"Comércio Mineiro","contactName":"Pedro Afonso","contactTitle":"Sales Associate","address":{"street":"23 Av. dos LusÃadas","city":"Sao Paulo","region":"SP","postalCode":"05432-043","country":"Brazil","phone":"(11) 555-7647"}},{"customerID":"CONSH","companyName":"Consolidated Holdings","contactName":"Elizabeth Brown","contactTitle":"Sales Representative","address":{"street":"Berkeley Gardens 12 Brewery","city":"London","region":null,"postalCode":"WX1 6LT","country":"UK","phone":"(171) 555-2282"}},{"customerID":"ALFKI","companyName":"Alfreds Futterkiste","contactName":"Maria Anders","contactTitle":"Sales Representative","address":{"street":"Obere Str. 57","city":"Berlin","region":null,"postalCode":"12209","country":"Germany","phone":"030-0074321"}},{"customerID":"BOTTM","companyName":"Bottom-Dollar Markets","contactName":"Elizabeth Lincoln","contactTitle":"Accounting Manager","address":{"street":"23 Tsawassen Blvd.","city":"Tsawassen","region":"BC","postalCode":"T2F 8M4","country":"Canada","phone":"(604) 555-4729"}},{"customerID":"DRACD","companyName":"Drachenblut Delikatessen","contactName":"Sven Ottlieb","contactTitle":"Order Administrator","address":{"street":"Walserweg 21","city":"Aachen","region":null,"postalCode":"52066","country":"Germany","phone":"0241-039123"}},{"customerID":"DUMON","companyName":"Du monde entier","contactName":"Janine Labrune","contactTitle":"Owner","address":{"street":"67 rue des Cinquante Otages","city":"Nantes","region":null,"postalCode":"44000","country":"France","phone":"40.67.88.88"}},{"customerID":"FAMIA","companyName":"Familia Arquibaldo","contactName":"Aria Cruz","contactTitle":"Marketing Assistant","address":{"street":"Rua Orós 92","city":"Sao Paulo","region":"SP","postalCode":"05442-030","country":"Brazil","phone":"(11) 555-9857"}},{"customerID":"FISSA","companyName":"FISSA Fabrica Inter. Salchichas S.A.","contactName":"Diego Roel","contactTitle":"Accounting Manager","address":{"street":"C/ Moralzarzal 86","city":"Madrid","region":null,"postalCode":"28034","country":"Spain","phone":"(91) 555 94 44"}},{"customerID":"FOLIG","companyName":"Folies gourmandes","contactName":"Martine Rancé","contactTitle":"Assistant Sales Agent","address":{"street":"184 chaussée de Tournai","city":"Lille","region":null,"postalCode":"59000","country":"France","phone":"20.16.10.16"}},{"customerID":"FOLKO","companyName":"Folk och fä HB","contactName":"Maria Larsson","contactTitle":"Owner","address":{"street":"Ã…kergatan 24","city":"Bräcke","region":null,"postalCode":"S-844 67","country":"Sweden","phone":"0695-34 67 21"}},{"customerID":"FRANK","companyName":"Frankenversand","contactName":"Peter Franken","contactTitle":"Marketing Manager","address":{"street":"Berliner Platz 43","city":"München","region":null,"postalCode":"80805","country":"Germany","phone":"089-0877310"}},{"customerID":"FRANR","companyName":"France restauration","contactName":"Carine Schmitt","contactTitle":"Marketing Manager","address":{"street":"54 rue Royale","city":"Nantes","region":null,"postalCode":"44000","country":"France","phone":"40.32.21.21"}},{"customerID":"EASTC","companyName":"Eastern Connection","contactName":"Ann Devon","contactTitle":"Sales Agent","address":{"street":"35 King George","city":"London","region":null,"postalCode":"WX3 6FW","country":"UK","phone":"(171) 555-0297"}},{"customerID":"ERNSH","companyName":"Ernst Handel","contactName":"Roland Mendel","contactTitle":"Sales Manager","address":{"street":"Kirchgasse 6","city":"Graz","region":null,"postalCode":"8010","country":"Austria","phone":"7675-3425"}},{"customerID":"FRANS","companyName":"Franchi S.p.A.","contactName":"Paolo Accorti","contactTitle":"Sales Representative","address":{"street":"Via Monte Bianco 34","city":"Torino","region":null,"postalCode":"10100","country":"Italy","phone":"011-4988260"}},{"customerID":"FURIB","companyName":"Furia Bacalhau e Frutos do Mar","contactName":"Lino Rodriguez","contactTitle":"Sales Manager","address":{"street":"Jardim das rosas n. 32","city":"Lisboa","region":null,"postalCode":"1675","country":"Portugal","phone":"(1) 354-2534"}},{"customerID":"GALED","companyName":"GalerÃa del gastrónomo","contactName":"Eduardo Saavedra","contactTitle":"Marketing Manager","address":{"street":"Rambla de Cataluña 23","city":"Barcelona","region":null,"postalCode":"8022","country":"Spain","phone":"(93) 203 4560"}},{"customerID":"GODOS","companyName":"Godos Cocina TÃpica","contactName":"José Pedro Freyre","contactTitle":"Sales Manager","address":{"street":"C/ Romero 33","city":"Sevilla","region":null,"postalCode":"41101","country":"Spain","phone":"(95) 555 82 82"}},{"customerID":"GOURL","companyName":"Gourmet Lanchonetes","contactName":"André Fonseca","contactTitle":"Sales Associate","address":{"street":"Av. Brasil 442","city":"Campinas","region":"SP","postalCode":"04876-786","country":"Brazil","phone":"(11) 555-9482"}},{"customerID":"HILAA","companyName":"HILARION-Abastos","contactName":"Carlos Hernández","contactTitle":"Sales Representative","address":{"street":"Carrera 22 con Ave. Carlos Soublette #8-35","city":"San Cristóbal","region":"Táchira","postalCode":"5022","country":"Venezuela","phone":"(5) 555-1340"}},{"customerID":"HUNGC","companyName":"Hungry Coyote Import Store","contactName":"Yoshi Latimer","contactTitle":"Sales Representative","address":{"street":"City Center Plaza 516 Main St.","city":"Elgin","region":"OR","postalCode":"97827","country":"USA","phone":"(503) 555-6874"}},{"customerID":"HUNGO","companyName":"Hungry Owl All-Night Grocers","contactName":"Patricia McKenna","contactTitle":"Sales Associate","address":{"street":"8 Johnstown Road","city":"Cork","region":"Co. Cork","postalCode":null,"country":"Ireland","phone":"2967 542"}},{"customerID":"ISLAT","companyName":"Island Trading","contactName":"Helen Bennett","contactTitle":"Marketing Manager","address":{"street":"Garden House Crowther Way","city":"Cowes","region":"Isle of Wight","postalCode":"PO31 7PJ","country":"UK","phone":"(198) 555-8888"}},{"customerID":"KOENE","companyName":"Königlich Essen","contactName":"Philip Cramer","contactTitle":"Sales Associate","address":{"street":"Maubelstr. 90","city":"Brandenburg","region":null,"postalCode":"14776","country":"Germany","phone":"0555-09876"}},{"customerID":"LACOR","companyName":"La corne d'abondance","contactName":"Daniel Tonini","contactTitle":"Sales Representative","address":{"street":"67 avenue de l'Europe","city":"Versailles","region":null,"postalCode":"78000","country":"France","phone":"30.59.84.10"}},{"customerID":"GROSR","companyName":"GROSELLA-Restaurante","contactName":"Manuel Pereira","contactTitle":"Owner","address":{"street":"5ª Ave. Los Palos Grandes","city":"Caracas","region":"DF","postalCode":"1081","country":"Venezuela","phone":"(2) 283-2951"}},{"customerID":"HANAR","companyName":"Hanari Carnes","contactName":"Mario Pontes","contactTitle":"Accounting Manager","address":{"street":"Rua do Paço 67","city":"Rio de Janeiro","region":"RJ","postalCode":"05454-876","country":"Brazil","phone":"(21) 555-0091"}},{"customerID":"LAUGB","companyName":"Laughing Bacchus Wine Cellars","contactName":"Yoshi Tannamuri","contactTitle":"Marketing Assistant","address":{"street":"1900 Oak St.","city":"Vancouver","region":"BC","postalCode":"V3F 2K1","country":"Canada","phone":"(604) 555-3392"}},{"customerID":"LAZYK","companyName":"Lazy K Kountry Store","contactName":"John Steel","contactTitle":"Marketing Manager","address":{"street":"12 Orchestra Terrace","city":"Walla Walla","region":"WA","postalCode":"99362","country":"USA","phone":"(509) 555-7969"}},{"customerID":"LEHMS","companyName":"Lehmanns Marktstand","contactName":"Renate Messner","contactTitle":"Sales Representative","address":{"street":"Magazinweg 7","city":"Frankfurt a.M.","region":null,"postalCode":"60528","country":"Germany","phone":"069-0245984"}},{"customerID":"GREAL","companyName":"Great Lakes Food Market","contactName":"Howard Snyder","contactTitle":"Marketing Manager","address":{"street":"2732 Baker Blvd.","city":"Eugene","region":"OR","postalCode":"97403","country":"USA","phone":"(503) 555-7555"}},{"customerID":"LAMAI","companyName":"La maison d'Asie","contactName":"Annette Roulet","contactTitle":"Sales Manager","address":{"street":"1 rue Alsace-Lorraine","city":"Toulouse","region":null,"postalCode":"31000","country":"France","phone":"61.77.61.10"}},{"customerID":"LETSS","companyName":"Let's Stop N Shop","contactName":"Jaime Yorres","contactTitle":"Owner","address":{"street":"87 Polk St. Suite 5","city":"San Francisco","region":"CA","postalCode":"94117","country":"USA","phone":"(415) 555-5938"}},{"customerID":"MAGAA","companyName":"Magazzini Alimentari Riuniti","contactName":"Giovanni Rovelli","contactTitle":"Marketing Manager","address":{"street":"Via Ludovico il Moro 22","city":"Bergamo","region":null,"postalCode":"24100","country":"Italy","phone":"035-640230"}},{"customerID":"MAISD","companyName":"Maison Dewey","contactName":"Catherine Dewey","contactTitle":"Sales Agent","address":{"street":"Rue Joseph-Bens 532","city":"Bruxelles","region":null,"postalCode":"B-1180","country":"Belgium","phone":"(02) 201 24 67"}},{"customerID":"MEREP","companyName":"Mère Paillarde","contactName":"Jean Fresnière","contactTitle":"Marketing Assistant","address":{"street":"43 rue St. Laurent","city":"Montréal","region":"Québec","postalCode":"H1J 1C3","country":"Canada","phone":"(514) 555-8054"}},{"customerID":"MORGK","companyName":"Morgenstern Gesundkost","contactName":"Alexander Feuer","contactTitle":"Marketing Assistant","address":{"street":"Heerstr. 22","city":"Leipzig","region":null,"postalCode":"4179","country":"Germany","phone":"0342-023176"}},{"customerID":"NORTS","companyName":"North/South","contactName":"Simon Crowther","contactTitle":"Sales Associate","address":{"street":"South House 300 Queensbridge","city":"London","region":null,"postalCode":"SW7 1RZ","country":"UK","phone":"(171) 555-7733"}},{"customerID":"OCEAN","companyName":"Océano Atlántico Ltda.","contactName":"Yvonne Moncada","contactTitle":"Sales Agent","address":{"street":"Ing. Gustavo Moncada 8585 Piso 20-A","city":"Buenos Aires","region":null,"postalCode":"1010","country":"Argentina","phone":"(1) 135-5333"}},{"customerID":"LINOD","companyName":"LINO-Delicateses","contactName":"Felipe Izquierdo","contactTitle":"Owner","address":{"street":"Ave. 5 de Mayo Porlamar","city":"I. de Margarita","region":"Nueva Esparta","postalCode":"4980","country":"Venezuela","phone":"(8) 34-56-12"}},{"customerID":"LILAS","companyName":"LILA-Supermercado","contactName":"Carlos González","contactTitle":"Accounting Manager","address":{"street":"Carrera 52 con Ave. BolÃvar #65-98 Llano Largo","city":"Barquisimeto","region":"Lara","postalCode":"3508","country":"Venezuela","phone":"(9) 331-6954"}},{"customerID":"OLDWO","companyName":"Old World Delicatessen","contactName":"Rene Phillips","contactTitle":"Sales Representative","address":{"street":"2743 Bering St.","city":"Anchorage","region":"AK","postalCode":"99508","country":"USA","phone":"(907) 555-7584"}},{"customerID":"OTTIK","companyName":"Ottilies Käseladen","contactName":"Henriette Pfalzheim","contactTitle":"Owner","address":{"street":"Mehrheimerstr. 369","city":"Köln","region":null,"postalCode":"50739","country":"Germany","phone":"0221-0644327"}},{"customerID":"PICCO","companyName":"Piccolo und mehr","contactName":"Georg Pipps","contactTitle":"Sales Manager","address":{"street":"Geislweg 14","city":"Salzburg","region":null,"postalCode":"5020","country":"Austria","phone":"6562-9722"}},{"customerID":"PARIS","companyName":"Paris spécialités","contactName":"Marie Bertrand","contactTitle":"Owner","address":{"street":"265 boulevard Charonne","city":"Paris","region":null,"postalCode":"75012","country":"France","phone":"(1) 42.34.22.66"}},{"customerID":"PERIC","companyName":"Pericles Comidas clásicas","contactName":"Guillermo Fernández","contactTitle":"Sales Representative","address":{"street":"Calle Dr. Jorge Cash 321","city":"México D.F.","region":null,"postalCode":"5033","country":"Mexico","phone":"(5) 552-3745"}},{"customerID":"PRINI","companyName":"Princesa Isabel Vinhos","contactName":"Isabel de Castro","contactTitle":"Sales Representative","address":{"street":"Estrada da saúde n. 58","city":"Lisboa","region":null,"postalCode":"1756","country":"Portugal","phone":"(1) 356-5634"}},{"customerID":"LONEP","companyName":"Lonesome Pine Restaurant","contactName":"Fran Wilson","contactTitle":"Sales Manager","address":{"street":"89 Chiaroscuro Rd.","city":"Portland","region":"OR","postalCode":"97219","country":"USA","phone":"(503) 555-9573"}},{"customerID":"QUEEN","companyName":"Queen Cozinha","contactName":"Lúcia Carvalho","contactTitle":"Marketing Assistant","address":{"street":"Alameda dos Canà rios 891","city":"Sao Paulo","region":"SP","postalCode":"05487-020","country":"Brazil","phone":"(11) 555-1189"}},{"customerID":"RATTC","companyName":"Rattlesnake Canyon Grocery","contactName":"Paula Wilson","contactTitle":"Assistant Sales Representative","address":{"street":"2817 Milton Dr.","city":"Albuquerque","region":"NM","postalCode":"87110","country":"USA","phone":"(505) 555-5939"}},{"customerID":"REGGC","companyName":"Reggiani Caseifici","contactName":"Maurizio Moroni","contactTitle":"Sales Associate","address":{"street":"Strada Provinciale 124","city":"Reggio Emilia","region":null,"postalCode":"42100","country":"Italy","phone":"0522-556721"}},{"customerID":"QUEDE","companyName":"Que DelÃcia","contactName":"Bernardo Batista","contactTitle":"Accounting Manager","address":{"street":"Rua da Panificadora","city":"12Rio de Janeiro","region":"RJ","postalCode":"02389-673","country":"Brazil","phone":"(21) 555-4252"}},{"customerID":"RANCH","companyName":"Rancho grande","contactName":"Sergio Gutiérrez","contactTitle":"Sales Representative","address":{"street":"Av. del Libertador 900","city":"Buenos Aires","region":null,"postalCode":"1010","country":"Argentina","phone":"(1) 123-5555"}},{"customerID":"ROMEY","companyName":"Romero y tomillo","contactName":"Alejandra Camino","contactTitle":"Accounting Manager","address":{"street":"Gran VÃa 1","city":"Madrid","region":null,"postalCode":"28001","country":"Spain","phone":"(91) 745 6200"}},{"customerID":"QUICK","companyName":"QUICK-Stop","contactName":"Horst Kloss","contactTitle":"Accounting Manager","address":{"street":"Taucherstraße 10","city":"Cunewalde","region":null,"postalCode":"1307","country":"Germany","phone":"0372-035188"}},{"customerID":"RICAR","companyName":"Ricardo Adocicados","contactName":"Janete Limeira","contactTitle":"Assistant Sales Agent","address":{"street":"Av. Copacabana 267","city":"Rio de Janeiro","region":"RJ","postalCode":"02389-890","country":"Brazil","phone":"(21) 555-3412"}},{"customerID":"RICSU","companyName":"Richter Supermarkt","contactName":"Michael Holz","contactTitle":"Sales Manager","address":{"street":"Grenzacherweg 237","city":"Genève","region":null,"postalCode":"1203","country":"Switzerland","phone":"0897-034214"}},{"customerID":"SANTG","companyName":"Santé Gourmet","contactName":"Jonas Bergulfsen","contactTitle":"Owner","address":{"street":"Erling Skakkes gate 78","city":"Stavern","region":null,"postalCode":"4110","country":"Norway","phone":"07-98 92 35"}},{"customerID":"SAVEA","companyName":"Save-a-lot Markets","contactName":"Jose Pavarotti","contactTitle":"Sales Representative","address":{"street":"187 Suffolk Ln.","city":"Boise","region":"ID","postalCode":"83720","country":"USA","phone":"(208) 555-8097"}},{"customerID":"SEVES","companyName":"Seven Seas Imports","contactName":"Hari Kumar","contactTitle":"Sales Manager","address":{"street":"90 Wadhurst Rd.","city":"London","region":null,"postalCode":"OX15 4NB","country":"UK","phone":"(171) 555-1717"}},{"customerID":"SIMOB","companyName":"Simons bistro","contactName":"Jytte Petersen","contactTitle":"Owner","address":{"street":"Vinbæltet 34","city":"Kobenhavn","region":null,"postalCode":"1734","country":"Denmark","phone":"31 12 34 56"}},{"customerID":"SPECD","companyName":"Spécialités du monde","contactName":"Dominique Perrier","contactTitle":"Marketing Manager","address":{"street":"25 rue Lauriston","city":"Paris","region":null,"postalCode":"75016","country":"France","phone":"(1) 47.55.60.10"}},{"customerID":"SPLIR","companyName":"Split Rail Beer & Ale","contactName":"Art Braunschweiger","contactTitle":"Sales Manager","address":{"street":"P.O. Box 555","city":"Lander","region":"WY","postalCode":"82520","country":"USA","phone":"(307) 555-4680"}},{"customerID":"SUPRD","companyName":"Suprêmes délices","contactName":"Pascale Cartrain","contactTitle":"Accounting Manager","address":{"street":"Boulevard Tirou 255","city":"Charleroi","region":null,"postalCode":"B-6000","country":"Belgium","phone":"(071) 23 67 22 20"}},{"customerID":"THEBI","companyName":"The Big Cheese","contactName":"Liz Nixon","contactTitle":"Marketing Manager","address":{"street":"89 Jefferson Way Suite 2","city":"Portland","region":"OR","postalCode":"97201","country":"USA","phone":"(503) 555-3612"}},{"customerID":"THECR","companyName":"The Cracker Box","contactName":"Liu Wong","contactTitle":"Marketing Assistant","address":{"street":"55 Grizzly Peak Rd.","city":"Butte","region":"MT","postalCode":"59801","country":"USA","phone":"(406) 555-5834"}},{"customerID":"TOMSP","companyName":"Toms Spezialitäten","contactName":"Karin Josephs","contactTitle":"Marketing Manager","address":{"street":"Luisenstr. 48","city":"Münster","region":null,"postalCode":"44087","country":"Germany","phone":"0251-031259"}},{"customerID":"TORTU","companyName":"Tortuga Restaurante","contactName":"Miguel Angel Paolino","contactTitle":"Owner","address":{"street":"Avda. Azteca 123","city":"México D.F.","region":null,"postalCode":"5033","country":"Mexico","phone":"(5) 555-2933"}},{"customerID":"TRADH","companyName":"Tradição Hipermercados","contactName":"Anabela Domingues","contactTitle":"Sales Representative","address":{"street":"Av. Inês de Castro 414","city":"Sao Paulo","region":"SP","postalCode":"05634-030","country":"Brazil","phone":"(11) 555-2167"}},{"customerID":"TRAIH","companyName":"Trail's Head Gourmet Provisioners","contactName":"Helvetius Nagy","contactTitle":"Sales Associate","address":{"street":"722 DaVinci Blvd.","city":"Kirkland","region":"WA","postalCode":"98034","country":"USA","phone":"(206) 555-8257"}},{"customerID":"VAFFE","companyName":"Vaffeljernet","contactName":"Palle Ibsen","contactTitle":"Sales Manager","address":{"street":"Smagsloget 45","city":"Ã…rhus","region":null,"postalCode":"8200","country":"Denmark","phone":"86 21 32 43"}},{"customerID":"VICTE","companyName":"Victuailles en stock","contactName":"Mary Saveley","contactTitle":"Sales Agent","address":{"street":"2 rue du Commerce","city":"Lyon","region":null,"postalCode":"69004","country":"France","phone":"78.32.54.86"}},{"customerID":"VINET","companyName":"Vins et alcools Chevalier","contactName":"Paul Henriot","contactTitle":"Accounting Manager","address":{"street":"59 rue de l'Abbaye","city":"Reims","region":null,"postalCode":"51100","country":"France","phone":"26.47.15.10"}},{"customerID":"WANDK","companyName":"Die Wandernde Kuh","contactName":"Rita Müller","contactTitle":"Sales Representative","address":{"street":"Adenauerallee 900","city":"Stuttgart","region":null,"postalCode":"70563","country":"Germany","phone":"0711-020361"}},{"customerID":"WARTH","companyName":"Wartian Herkku","contactName":"Pirkko Koskitalo","contactTitle":"Accounting Manager","address":{"street":"Torikatu 38","city":"Oulu","region":null,"postalCode":"90110","country":"Finland","phone":"981-443655"}},{"customerID":"WELLI","companyName":"Wellington Importadora","contactName":"Paula Parente","contactTitle":"Sales Manager","address":{"street":"Rua do Mercado 12","city":"Resende","region":"SP","postalCode":"08737-363","country":"Brazil","phone":"(14) 555-8122"}},{"customerID":"WHITC","companyName":"White Clover Markets","contactName":"Karl Jablonski","contactTitle":"Owner","address":{"street":"305 - 14th Ave. S. Suite 3B","city":"Seattle","region":"WA","postalCode":"98128","country":"USA","phone":"(206) 555-4112"}},{"customerID":"WILMK","companyName":"Wilman Kala","contactName":"Matti Karttunen","contactTitle":"Owner/Marketing Assistant","address":{"street":"Keskuskatu 45","city":"Helsinki","region":null,"postalCode":"21240","country":"Finland","phone":"90-224 8858"}},{"customerID":"WOLZA","companyName":"Wolski Zajazd","contactName":"Zbyszek Piestrzeniewicz","contactTitle":"Owner","address":{"street":"ul. Filtrowa 68","city":"Warszawa","region":null,"postalCode":"01-012","country":"Poland","phone":"(26) 642-7012"}}],
+};
diff --git a/src/app/tasks/tasks.test.ts b/src/app/tasks/tasks.test.ts
new file mode 100644
index 0000000..6c99590
--- /dev/null
+++ b/src/app/tasks/tasks.test.ts
@@ -0,0 +1,9 @@
+import { expect } from '@open-wc/testing';
+import Tasks from './tasks.js';
+
+describe('Tasks', () => {
+ it(' is an instance of Tasks', async () => {
+ const element = document.createElement('app-tasks');
+ expect(element).to.be.instanceOf(Tasks);
+ });
+});
diff --git a/src/app/tasks/tasks.ts b/src/app/tasks/tasks.ts
new file mode 100644
index 0000000..8edce04
--- /dev/null
+++ b/src/app/tasks/tasks.ts
@@ -0,0 +1,72 @@
+import { html, css, LitElement } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('app-tasks')
+export default class Tasks extends LitElement {
+ static styles = css`
+ :host {
+ height: 100%;
+ display: flex;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+ }
+ .column-layout {
+ display: flex;
+ flex-direction: column;
+ }
+ .demo-content {
+ background-color: transparent;
+ border-color: hsla(var(--ig-gray-400));
+ border-width: 2px;
+ border-style: dashed;
+ justify-content: center;
+ align-items: center;
+ align-content: flex-start;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ position: absolute;
+ padding: 64px;
+ min-width: 50px;
+ min-height: 50px;
+ }
+ .image {
+ object-fit: cover;
+ margin: 0 0 24px;
+ min-width: 0;
+ min-height: 0;
+ max-width: 280px;
+ flex-shrink: 0;
+ }
+ .h5 {
+ color: hsla(var(--ig-secondary-800));
+ margin: 0 0 16px;
+ height: max-content;
+ min-width: min-content;
+ }
+ .text {
+ text-align: center;
+ color: hsla(var(--ig-gray-700));
+ margin: 0 0 24px;
+ height: max-content;
+ min-width: min-content;
+ max-width: 320px;
+ }
+ `;
+
+ render() {
+ return html`
+
+
+
+
+ Start building!
+
+
+ Remove the "demo-content" container, and add your own content.
+
+
+ `;
+ }
+}
diff --git a/src/assets/Account-List-Avatar-Icon.svg b/src/assets/Account-List-Avatar-Icon.svg
new file mode 100644
index 0000000..ab11dcb
--- /dev/null
+++ b/src/assets/Account-List-Avatar-Icon.svg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/Accounts Icon - Green.svg b/src/assets/Accounts Icon - Green.svg
new file mode 100644
index 0000000..f12085c
--- /dev/null
+++ b/src/assets/Accounts Icon - Green.svg
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/Accounts-Avatar-Icon.svg b/src/assets/Accounts-Avatar-Icon.svg
new file mode 100644
index 0000000..161d843
--- /dev/null
+++ b/src/assets/Accounts-Avatar-Icon.svg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/CRM Logo.svg b/src/assets/CRM Logo.svg
new file mode 100644
index 0000000..70af781
--- /dev/null
+++ b/src/assets/CRM Logo.svg
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/Calendar-Avatar-Icon.svg b/src/assets/Calendar-Avatar-Icon.svg
new file mode 100644
index 0000000..6bd3acd
--- /dev/null
+++ b/src/assets/Calendar-Avatar-Icon.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/assets/Contacts-Avatar-Icon.svg b/src/assets/Contacts-Avatar-Icon.svg
new file mode 100644
index 0000000..8169bc3
--- /dev/null
+++ b/src/assets/Contacts-Avatar-Icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/assets/Contacts-List-Avatar-Icon.svg b/src/assets/Contacts-List-Avatar-Icon.svg
new file mode 100644
index 0000000..17238be
--- /dev/null
+++ b/src/assets/Contacts-List-Avatar-Icon.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/Contracts-Avatar-Icon.svg b/src/assets/Contracts-Avatar-Icon.svg
new file mode 100644
index 0000000..b325c5c
--- /dev/null
+++ b/src/assets/Contracts-Avatar-Icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/assets/Home-Avatar-Icon.svg b/src/assets/Home-Avatar-Icon.svg
new file mode 100644
index 0000000..f099155
--- /dev/null
+++ b/src/assets/Home-Avatar-Icon.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/Reports-Avatar-Icon.svg b/src/assets/Reports-Avatar-Icon.svg
new file mode 100644
index 0000000..2d76e49
--- /dev/null
+++ b/src/assets/Reports-Avatar-Icon.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/assets/Tasks-Avatar-Icon.svg b/src/assets/Tasks-Avatar-Icon.svg
new file mode 100644
index 0000000..669518d
--- /dev/null
+++ b/src/assets/Tasks-Avatar-Icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/assets/start-building-dark.svg b/src/assets/start-building-dark.svg
new file mode 100644
index 0000000..d560e70
--- /dev/null
+++ b/src/assets/start-building-dark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/start-building.svg b/src/assets/start-building.svg
new file mode 100644
index 0000000..c418b8d
--- /dev/null
+++ b/src/assets/start-building.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..1a6b6bc
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,2 @@
+import './app/app.js';
+import './app/app-routing.js';
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..e06ecae
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,24 @@
+body {
+ background: hsla(var(--ig-surface-500, 0 0% 100%));
+ color: var(--ig-surface-500-contrast, black);
+ font-family: var(--ig-font-family);
+}
+
+html,
+body {
+ height: 100%;
+}
+
+/* minor CSS reset */
+body, h1, h2, h3, h4, h5, h6, p {
+ margin: 0;
+}
+
+html {
+ box-sizing: border-box;
+}
+
+img, video {
+ height: auto;
+ max-width: 100%;
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..aef874d
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "target": "es2018",
+ "module": "esnext",
+ "moduleResolution": "node",
+ "noEmitOnError": true,
+ "lib": [
+ "es2017",
+ "dom",
+ "dom.iterable"
+ ],
+ "strict": true,
+ "skipLibCheck": true,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "experimentalDecorators": true,
+ "importHelpers": true,
+ "outDir": "dist",
+ "sourceMap": true,
+ "inlineSources": true,
+ "rootDir": "./",
+ "declaration": true,
+ "incremental": true
+ },
+ "exclude": [
+ "test"
+ ],
+ "files": [
+ "src/index.ts"
+ ],
+ "include": [
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/tsconfig.test.json b/tsconfig.test.json
new file mode 100644
index 0000000..473725e
--- /dev/null
+++ b/tsconfig.test.json
@@ -0,0 +1,13 @@
+
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "test"
+ },
+ "exclude": [
+ "dist"
+ ],
+ "include": [
+ "**/*.ts"
+ ]
+}
diff --git a/web-dev-server.config.mjs b/web-dev-server.config.mjs
new file mode 100644
index 0000000..0325792
--- /dev/null
+++ b/web-dev-server.config.mjs
@@ -0,0 +1,27 @@
+// import { hmrPlugin, presets } from '@open-wc/dev-server-hmr';
+
+/** Use Hot Module replacement by adding --hmr to the start command */
+const hmr = process.argv.includes('--hmr');
+
+export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
+ open: '/',
+ /** Use regular watch mode if HMR is not enabled. */
+ watch: !hmr,
+ /** Resolve bare module imports */
+ nodeResolve: {
+ exportConditions: ['browser', 'development'],
+ },
+
+ /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
+ // esbuildTarget: 'auto'
+
+ /** Set appIndex to enable SPA routing */
+ appIndex: './index.html',
+
+ plugins: [
+ /** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */
+ // hmr && hmrPlugin({ exclude: ['**/*/node_modules/**/*'], presets: [presets.litElement] }),
+ ],
+
+ // See documentation for all available options
+});
diff --git a/web-test-runner.config.mjs b/web-test-runner.config.mjs
new file mode 100644
index 0000000..20068e9
--- /dev/null
+++ b/web-test-runner.config.mjs
@@ -0,0 +1,41 @@
+// import { playwrightLauncher } from '@web/test-runner-playwright';
+
+const filteredLogs = ['Running in dev mode', 'lit-html is in dev mode'];
+
+export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
+ /** Test files to run */
+ files: 'test/src/app/**/*.test.js',
+
+ /** Resolve bare module imports */
+ nodeResolve: {
+ exportConditions: ['browser', 'development'],
+ },
+
+ /** Filter out lit dev mode logs */
+ filterBrowserLogs(log) {
+ for (const arg of log.args) {
+ if (typeof arg === 'string' && filteredLogs.some(l => arg.includes(l))) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
+ // esbuildTarget: 'auto',
+
+ /** Amount of browsers to run concurrently */
+ // concurrentBrowsers: 2,
+
+ /** Amount of test files per browser to test concurrently */
+ // concurrency: 1,
+
+ /** Browsers to run tests on */
+ // browsers: [
+ // playwrightLauncher({ product: 'chromium' }),
+ // playwrightLauncher({ product: 'firefox' }),
+ // playwrightLauncher({ product: 'webkit' }),
+ // ],
+
+ // See documentation for all available options
+});