David Touitou 2 år sedan
förälder
incheckning
28e7dc37dd
100 ändrade filer med 16277 tillägg och 1 borttagningar
  1. 17
    0
      .browserslistrc
  2. 13
    0
      .editorconfig
  3. 50
    0
      .gitignore
  4. 265
    0
      CHANGELOG.md
  5. 1
    1
      README.md
  6. 134
    0
      angular.json
  7. 44
    0
      karma.conf.js
  8. 13403
    0
      package-lock.json
  9. 60
    0
      package.json
  10. 28
    0
      src/app/app-routing.module.ts
  11. 3
    0
      src/app/app.breadcrumb.component.html
  12. 31
    0
      src/app/app.breadcrumb.component.ts
  13. 15
    0
      src/app/app.breadcrumb.service.ts
  14. 68
    0
      src/app/app.code.component.scss
  15. 32
    0
      src/app/app.code.component.ts
  16. 1
    0
      src/app/app.component.html
  17. 0
    0
      src/app/app.component.scss
  18. 31
    0
      src/app/app.component.spec.ts
  19. 32
    0
      src/app/app.component.ts
  20. 339
    0
      src/app/app.config.component.ts
  21. 17
    0
      src/app/app.footer.component.ts
  22. 20
    0
      src/app/app.inlinemenu.component.html
  23. 63
    0
      src/app/app.inlinemenu.component.ts
  24. 38
    0
      src/app/app.main.component.html
  25. 238
    0
      src/app/app.main.component.ts
  26. 28
    0
      src/app/app.menu.component.ts
  27. 20
    0
      src/app/app.menu.service.ts
  28. 208
    0
      src/app/app.menuitem.component.ts
  29. 223
    0
      src/app/app.module.ts
  30. 70
    0
      src/app/app.rightmenu.component.html
  31. 11
    0
      src/app/app.rightmenu.component.ts
  32. 166
    0
      src/app/app.topbar.component.html
  33. 126
    0
      src/app/app.topbar.component.ts
  34. 25
    0
      src/app/pages/dashboard/dashboard.module.ts
  35. 79
    0
      src/app/pages/dashboard/dashboard/dashboard.component.html
  36. 0
    0
      src/app/pages/dashboard/dashboard/dashboard.component.scss
  37. 33
    0
      src/app/pages/dashboard/dashboard/dashboard.component.ts
  38. 12
    0
      src/app/pages/pages.module.ts
  39. 19
    0
      src/app/pages/pages.routing.module.ts
  40. 7
    0
      src/app/shared/models/candidate.ts
  41. 9
    0
      src/app/shared/services/candidate.service.ts
  42. 19
    0
      src/app/shared/services/node.service.ts
  43. 161
    0
      src/appdemo.scss
  44. 28
    0
      src/assets/demo/data/candidates.json
  45. 89
    0
      src/assets/demo/data/files.json
  46. Binär
      src/assets/demo/flags/flag_placeholder.png
  47. 1
    0
      src/assets/demo/flags/flags.css
  48. Binär
      src/assets/demo/flags/flags_responsive.png
  49. Binär
      src/assets/demo/images/avatar/activity-1.png
  50. Binär
      src/assets/demo/images/avatar/activity-2.png
  51. Binär
      src/assets/demo/images/avatar/activity-3.png
  52. Binär
      src/assets/demo/images/avatar/amyelsner.png
  53. Binär
      src/assets/demo/images/avatar/annafali.png
  54. Binär
      src/assets/demo/images/avatar/asiyajavayant.png
  55. Binär
      src/assets/demo/images/avatar/avatar-1.png
  56. Binär
      src/assets/demo/images/avatar/avatar-10.png
  57. Binär
      src/assets/demo/images/avatar/avatar-11.png
  58. Binär
      src/assets/demo/images/avatar/avatar-12.png
  59. Binär
      src/assets/demo/images/avatar/avatar-13.png
  60. Binär
      src/assets/demo/images/avatar/avatar-14.png
  61. Binär
      src/assets/demo/images/avatar/avatar-15.png
  62. Binär
      src/assets/demo/images/avatar/avatar-16.png
  63. Binär
      src/assets/demo/images/avatar/avatar-2.png
  64. Binär
      src/assets/demo/images/avatar/avatar-3.png
  65. Binär
      src/assets/demo/images/avatar/avatar-4.png
  66. Binär
      src/assets/demo/images/avatar/avatar-5.png
  67. Binär
      src/assets/demo/images/avatar/avatar-6.png
  68. Binär
      src/assets/demo/images/avatar/avatar-7.png
  69. Binär
      src/assets/demo/images/avatar/avatar-8.png
  70. Binär
      src/assets/demo/images/avatar/avatar-9.png
  71. Binär
      src/assets/demo/images/avatar/bernardodominic.png
  72. Binär
      src/assets/demo/images/avatar/elwinsharvill.png
  73. Binär
      src/assets/demo/images/avatar/ionibowcher.png
  74. Binär
      src/assets/demo/images/avatar/ivanmagalhaes.png
  75. Binär
      src/assets/demo/images/avatar/onyamalimba.png
  76. Binär
      src/assets/demo/images/avatar/profile.jpg
  77. Binär
      src/assets/demo/images/avatar/stephenshaw.png
  78. Binär
      src/assets/demo/images/avatar/xuxuefeng.png
  79. Binär
      src/assets/demo/images/galleria/galleria1.jpg
  80. Binär
      src/assets/demo/images/galleria/galleria10.jpg
  81. Binär
      src/assets/demo/images/galleria/galleria10s.jpg
  82. Binär
      src/assets/demo/images/galleria/galleria11.jpg
  83. Binär
      src/assets/demo/images/galleria/galleria11s.jpg
  84. Binär
      src/assets/demo/images/galleria/galleria12.jpg
  85. Binär
      src/assets/demo/images/galleria/galleria12s.jpg
  86. Binär
      src/assets/demo/images/galleria/galleria13.jpg
  87. Binär
      src/assets/demo/images/galleria/galleria13s.jpg
  88. Binär
      src/assets/demo/images/galleria/galleria14.jpg
  89. Binär
      src/assets/demo/images/galleria/galleria14s.jpg
  90. Binär
      src/assets/demo/images/galleria/galleria15.jpg
  91. Binär
      src/assets/demo/images/galleria/galleria15s.jpg
  92. Binär
      src/assets/demo/images/galleria/galleria1s.jpg
  93. Binär
      src/assets/demo/images/galleria/galleria2.jpg
  94. Binär
      src/assets/demo/images/galleria/galleria2s.jpg
  95. Binär
      src/assets/demo/images/galleria/galleria3.jpg
  96. Binär
      src/assets/demo/images/galleria/galleria3s.jpg
  97. Binär
      src/assets/demo/images/galleria/galleria4.jpg
  98. Binär
      src/assets/demo/images/galleria/galleria4s.jpg
  99. Binär
      src/assets/demo/images/galleria/galleria5.jpg
  100. 0
    0
      src/assets/demo/images/galleria/galleria5s.jpg

+ 17
- 0
.browserslistrc Visa fil

@@ -0,0 +1,17 @@
1
+# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2
+# For additional information regarding the format and rule options, please see:
3
+# https://github.com/browserslist/browserslist#queries
4
+
5
+# For the full list of supported browsers by the Angular framework, please see:
6
+# https://angular.io/guide/browser-support
7
+
8
+# You can see what browsers were selected by your queries by running:
9
+#   npx browserslist
10
+
11
+last 1 Chrome version
12
+last 1 Firefox version
13
+last 2 Edge major versions
14
+last 2 Safari major versions
15
+last 2 iOS major versions
16
+Firefox ESR
17
+not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.

+ 13
- 0
.editorconfig Visa fil

@@ -0,0 +1,13 @@
1
+# Editor configuration, see http://editorconfig.org
2
+root = true
3
+
4
+[*]
5
+charset = utf-8
6
+indent_style = space
7
+indent_size = 4
8
+insert_final_newline = true
9
+trim_trailing_whitespace = true
10
+
11
+[*.md]
12
+max_line_length = off
13
+trim_trailing_whitespace = false

+ 50
- 0
.gitignore Visa fil

@@ -0,0 +1,50 @@
1
+# See http://help.github.com/ignore-files/ for more about ignoring files.
2
+
3
+# compiled output
4
+/dist
5
+/build
6
+/tmp
7
+/out-tsc
8
+
9
+# dependencies
10
+/node_modules
11
+
12
+# profiling files
13
+chrome-profiler-events.json
14
+speed-measure-plugin.json
15
+
16
+# IDEs and editors
17
+/.idea
18
+.project
19
+.classpath
20
+.c9/
21
+*.launch
22
+.settings/
23
+*.sublime-workspace
24
+
25
+# IDE - VSCode
26
+.vscode/*
27
+!.vscode/settings.json
28
+!.vscode/tasks.json
29
+!.vscode/launch.json
30
+!.vscode/extensions.json
31
+
32
+# misc
33
+/.sass-cache
34
+sassdoc
35
+/connect.lock
36
+/coverage
37
+/libpeerconnection.log
38
+npm-debug.log
39
+yarn-error.log
40
+testem.log
41
+/typings
42
+
43
+# System Files
44
+.DS_Store
45
+Thumbs.db
46
+
47
+theme.css
48
+src/assets/theme/*/theme-*.css
49
+src/assets/layout/css/*.css
50
+src/assets/sass/theme/designer

+ 265
- 0
CHANGELOG.md Visa fil

@@ -0,0 +1,265 @@
1
+# Changelog
2
+
3
+## 12.2.0
4
+**Migration Guide**
5
+- Update theme files and layout files.
6
+
7
+**Implemented New Features and Enhancements:**
8
+
9
+- Styles of new PrimeNG components
10
+
11
+## 12.0.0
12
+**Migration Guide**
13
+- Update your project to Angular 12.
14
+- Update app.* components
15
+- Update theme files and layout files.
16
+
17
+**Implemented New Features and Enhancements:**
18
+
19
+- Upgrade to Angular and PrimeNG 12
20
+- Styles of new PrimeNG components
21
+- PrimeFlex 3+ support
22
+
23
+## 11.0.1
24
+**Migration Guide**
25
+- Update theme files and layout files.
26
+
27
+**Fixed bugs:**
28
+
29
+- Search panel is not visible (dark mode)
30
+
31
+## 11.0.0
32
+**Migration Guide**
33
+- Update your project to Angular 11.
34
+- Update app.main.component.ts and app.component.ts
35
+- Update app.menu.component.ts and app.menuitem.component.ts
36
+- Update theme files and layout files.
37
+
38
+**Implemented New Features and Enhancements:**
39
+
40
+- Upgrade to Angular and PrimeNG 11
41
+- Styles of new PrimeNG components
42
+
43
+## 10.1.0
44
+
45
+**Migration Guide**
46
+- Update theme files and layout files.
47
+- Update app.* components
48
+- Use app.inlinemenu.component instead of app.profile.component
49
+
50
+**Implemented New Features and Enhancements:**
51
+
52
+- Implemented new Ultima design
53
+- Added dark mode, topbar and menu colors
54
+
55
+## 10.0.1
56
+
57
+**Migration Guide**
58
+- Update app.component.ts and app.main.component.ts
59
+- Update app.login.component.html
60
+- Update layout css files.
61
+- Update theme css files.
62
+
63
+**Fixed bugs:**
64
+
65
+- Ripple effect is not working outside of the main application
66
+- Ripple effect is not working on Login page
67
+
68
+## 10.0.0
69
+
70
+**Migration Guide**
71
+- Update your project to Angular 10.
72
+- Update theme files and layout files.
73
+
74
+**Implemented New Features and Enhancements:**
75
+
76
+- Migrate to PrimeOne Design Architecture
77
+- Upgrade to Angular and PrimeNG 10
78
+
79
+## 8.0.1 to 9.0.0
80
+
81
+Angular 9 and PrimeNG 9
82
+
83
+- Update dependencies with [ng update](https://angular.io/cli/update).
84
+- Update theme.css and layout.css files.
85
+- Update app.menu.component.ts while retaining your MenuModel.
86
+- Include app.menuitem.component.ts under app folder and define it app.module.ts with declarations property.
87
+- Include app.menu.service.ts under app folder and define it app.module.ts with providers property.
88
+
89
+## 8.0.0 to 8.0.1
90
+
91
+- Update layout css files.
92
+- Update theme css files.
93
+
94
+## 7.1.1 to 8.0.0
95
+
96
+- Update your project to Angular 8 with ng update. View the official update guide -[https://update.angular.io/](https://update.angular.io/)- for more information.
97
+- Update app.main.component.ts.
98
+- Update app.menu.component.ts.
99
+- Update app.rightpanel.component.ts.
100
+- Update layout css files.
101
+- Update theme css files.
102
+
103
+## 7.1.0 to 7.1.1
104
+
105
+- Update layout css files.
106
+- Update theme css files.
107
+
108
+## 7.0.1 to 7.1.0
109
+
110
+- Update layout css files.
111
+- Update theme css files.
112
+
113
+## 7.0.0 to 7.0.1
114
+
115
+- Update theme css files.
116
+
117
+## 6.1.1 to 7.0.0
118
+
119
+- Update layout css files.
120
+- Update theme css files.
121
+
122
+## 6.1.0 to 6.1.1
123
+
124
+- Update layout css files.
125
+- Update theme css files.
126
+
127
+## 6.0.0 to 6.1.0
128
+
129
+Adds support for new features in PrimeNG 6.1.x
130
+
131
+- Update theme css files.
132
+
133
+## 5.2.4 to 6.0.0
134
+
135
+Brings support for Angular 6 and RxJS 6, adds theming for new components in PrimeNG such as the new TreeTable and improves behaviors of the layout menus.
136
+
137
+- Update app.module.ts and app.component.ts.
138
+- Update app.topbar.component.ts.
139
+- Update app.profile.component.ts.
140
+- Update app.menu.component.ts.
141
+- Update app.breadcrumb.component.ts and app.breadcrumb.service.ts.
142
+- Update layout css files.
143
+- Update theme css files.
144
+
145
+## 5.2.3 to 5.2.4
146
+
147
+- Update theme css files.
148
+
149
+## 5.2.2 to 5.2.3
150
+
151
+- Update layout css files.
152
+- Update theme css files.
153
+
154
+## 5.2.1 to 5.2.2
155
+
156
+- Update layout css files.
157
+- Update theme css files.
158
+
159
+## 5.2.0 to 5.2.1
160
+
161
+Aligns input focus animation with the Material specs.
162
+
163
+- Update layout css files.
164
+- Update theme css files.
165
+
166
+## 5.0.0 to 5.2.0
167
+
168
+Adds support for PrimeNG 5.2.0 (e.g. TurboTable), replaces nanoscroller with PrimeNG ScrollPanel and reimplements ripple effect to run outside of NgZone for better performance.
169
+
170
+- Remove nanoscroller as it is replaced by ScrollPanel component of PrimeNG.
171
+- Update app.component.ts and app.component.html.
172
+- Update app.menu.component.ts.
173
+- Update app.rightpanel.component.ts.
174
+- Update layout css files.
175
+- Update theme css files.
176
+
177
+## 4.3.0 to 5.0.0
178
+
179
+- Update app.component.ts and app.component.html.
180
+- Define breadcrumbservice as a provider in your app.module
181
+- Update layout css files.
182
+- Update theme css files.
183
+
184
+## 4.2.0 to 4.3.0
185
+
186
+- Update theme css files.
187
+
188
+## 4.1.1 to 4.2.0
189
+
190
+- Update app.*.ts and app.*.html files under app folder.
191
+- Update theme css and layout css files.
192
+
193
+## 4.0.1 to 4.1.0
194
+
195
+- Update layout css files.
196
+- Update theme css files.
197
+- Update AppSubmenu component in app.menu.component.ts.
198
+
199
+## 4.0.0 to 4.0.1
200
+
201
+- Update layout css files.
202
+
203
+## 2.1 to 4.0.0
204
+
205
+- Includes version updates to PrimeNG 4 and Angular 4.
206
+- Update theme css files.
207
+
208
+## 2.0.5 to 2.1.0
209
+
210
+- Project is updated to CLI RC2, Angular 4-RC3 and PrimeNG 4-RC1.
211
+- Add _import {trigger,state,style,transition,animate} from '@angular/animations';_ to app.menu.components.ts and remove these imports from 'angular/core'.
212
+- Add _import {BrowserAnimationsModule} from '@angular/platform-browser/animations';_ to app.module.ts and import the module to your application.
213
+- Update theme css files, there are no changes to the layout.
214
+
215
+## 2.0.4 to 2.0.5
216
+
217
+- No change required, missing .angular-cli.json file in 2.0.4 is added.
218
+
219
+## 2.0.3 to 2.0.4
220
+
221
+- No change required, only CLI version is updated to RC
222
+
223
+## 2.0.2 to 2.0.3
224
+
225
+- Update AppSubmenu component in app.menu.component.ts by replacing the itemClick method implementation.
226
+- Update layout css files, there are no changes on themes.
227
+- Update app.component.ts by changing onTopbarMenuButtonClick method implementation to add _event.preventDefault()_ at the end.
228
+- Remove [ngClass]="{'menu-button-rotate': app.rotateMenuButton}" from menu-button in app.topbar.component.ts.
229
+
230
+## 2.0.1 to 2.0.2
231
+
232
+- Update AppSubmenu component in app.menu.component.ts
233
+- Update layout css files, there are no changes on themes.
234
+- Update app.component.ts.
235
+- Add pInputText to search input at app.topbar.component.ts
236
+
237
+## 2.0.0 to 2.0.1
238
+
239
+- Update AppSubmenu component in app.menu.component.ts
240
+- Update layout css and theme css files.
241
+- Update app.component.ts.
242
+
243
+## 1.1.0 to 2.0.0
244
+
245
+- Update PrimeNG to at least 2.0.
246
+- Replace app.component.ts and app.component.html
247
+- Remove layout.js
248
+- Update the scripts and styles section at angular-cli.json
249
+- Define menu using PrimeNG MenuModel
250
+
251
+## 1.0.3 to 1.1.0
252
+
253
+- Update css files of layout and theme.
254
+
255
+## 1.0.2 to 1.0.3
256
+
257
+- Update css files of layout and theme.
258
+
259
+## 1.0.1 to 1.0.2
260
+
261
+- Update layout.js
262
+
263
+## 1.0.0 to 1.0.1
264
+
265
+- Update layout.js

+ 1
- 1
README.md Visa fil

@@ -1,2 +1,2 @@
1
-# ealexondoa
1
+# oussamaakallouch
2 2
 

+ 134
- 0
angular.json Visa fil

@@ -0,0 +1,134 @@
1
+{
2
+    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+    "version": 1,
4
+    "newProjectRoot": "projects",
5
+    "projects": {
6
+        "ultima-cli": {
7
+            "projectType": "application",
8
+            "schematics": {
9
+                "@schematics/angular:component": {
10
+                    "style": "scss"
11
+                }
12
+            },
13
+            "root": "",
14
+            "sourceRoot": "src",
15
+            "prefix": "app",
16
+            "architect": {
17
+                "build": {
18
+                    "builder": "@angular-devkit/build-angular:browser",
19
+                    "options": {
20
+                        "outputPath": "dist/ultima",
21
+                        "index": "src/index.html",
22
+                        "main": "src/main.ts",
23
+                        "polyfills": "src/polyfills.ts",
24
+                        "tsConfig": "tsconfig.app.json",
25
+                        "aot": true,
26
+                        "assets": [
27
+                            "src/assets",
28
+                            "src/upload.php"
29
+                        ],
30
+                        "styles": [
31
+                            "src/styles.scss"
32
+                        ],
33
+                        "scripts": [
34
+                            "node_modules/prismjs/prism.js",
35
+                            "node_modules/prismjs/components/prism-typescript.js"
36
+                        ],
37
+                        "allowedCommonJsDependencies": [
38
+                            "@fullcalendar/daygrid",
39
+                            "@fullcalendar/timegrid",
40
+                            "@fullcalendar/interaction",
41
+                            "chart.js"
42
+                        ]
43
+                    },
44
+                    "configurations": {
45
+                        "production": {
46
+                            "budgets": [
47
+                                {
48
+                                    "type": "initial",
49
+                                    "maximumWarning": "3mb",
50
+                                    "maximumError": "5mb"
51
+                                },
52
+                                {
53
+                                    "type": "anyComponentStyle",
54
+                                    "maximumWarning": "6kb",
55
+                                    "maximumError": "10kb"
56
+                                }
57
+                            ],
58
+                            "fileReplacements": [
59
+                                {
60
+                                    "replace": "src/environments/environment.ts",
61
+                                    "with": "src/environments/environment.prod.ts"
62
+                                }
63
+                            ],
64
+                            "outputHashing": "all"
65
+                        },
66
+                        "development": {
67
+                            "buildOptimizer": false,
68
+                            "optimization": false,
69
+                            "vendorChunk": true,
70
+                            "extractLicenses": false,
71
+                            "sourceMap": true,
72
+                            "namedChunks": true
73
+                        }
74
+                    },
75
+                    "defaultConfiguration": "production"
76
+                },
77
+                "serve": {
78
+                    "builder": "@angular-devkit/build-angular:dev-server",
79
+                    "options": {
80
+                        "browserTarget": "ultima-cli:build"
81
+                    },
82
+                    "configurations": {
83
+                        "production": {
84
+                            "browserTarget": "ultima-cli:build:production"
85
+                        },
86
+                        "development": {
87
+                            "browserTarget": "ultima-cli:build:development"
88
+                        }
89
+                    },
90
+                    "defaultConfiguration": "development"
91
+                },
92
+                "extract-i18n": {
93
+                    "builder": "@angular-devkit/build-angular:extract-i18n",
94
+                    "options": {
95
+                        "browserTarget": "ultima-cli:build"
96
+                    }
97
+                },
98
+                "test": {
99
+                    "builder": "@angular-devkit/build-angular:karma",
100
+                    "options": {
101
+                        "main": "src/test.ts",
102
+                        "polyfills": "src/polyfills.ts",
103
+                        "tsConfig": "tsconfig.spec.json",
104
+                        "karmaConfig": "karma.conf.js",
105
+                        "scripts": [],
106
+                        "styles": [
107
+                            "src/styles.scss"
108
+                        ],
109
+                        "assets": [
110
+                            "src/assets",
111
+                            "src/upload.php"
112
+                        ]
113
+                    }
114
+                },
115
+                "lint": {
116
+                    "builder": "@angular-devkit/build-angular:tslint",
117
+                    "options": {
118
+                        "tsConfig": [
119
+                            "tsconfig.app.json",
120
+                            "tsconfig.spec.json"
121
+                        ],
122
+                        "exclude": [
123
+                            "**/node_modules/**"
124
+                        ]
125
+                    }
126
+                }
127
+            }
128
+        }
129
+    },
130
+    "defaultProject": "ultima-cli",
131
+    "cli": {
132
+        "analytics": false
133
+    }
134
+}

+ 44
- 0
karma.conf.js Visa fil

@@ -0,0 +1,44 @@
1
+// Karma configuration file, see link for more information
2
+// https://karma-runner.github.io/1.0/config/configuration-file.html
3
+
4
+module.exports = function (config) {
5
+    config.set({
6
+        basePath: '',
7
+        frameworks: ['jasmine', '@angular-devkit/build-angular'],
8
+        plugins: [
9
+            require('karma-jasmine'),
10
+            require('karma-chrome-launcher'),
11
+            require('karma-jasmine-html-reporter'),
12
+            require('karma-coverage'),
13
+            require('@angular-devkit/build-angular/plugins/karma')
14
+        ],
15
+        client: {
16
+            jasmine: {
17
+                // you can add configuration options for Jasmine here
18
+                // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19
+                // for example, you can disable the random execution with `random: false`
20
+                // or set a specific seed with `seed: 4321`
21
+            },
22
+            clearContext: false // leave Jasmine Spec Runner output visible in browser
23
+        },
24
+        jasmineHtmlReporter: {
25
+            suppressAll: true // removes the duplicated traces
26
+        },
27
+        coverageReporter: {
28
+            dir: require('path').join(__dirname, './coverage/forupdate'),
29
+            subdir: '.',
30
+            reporters: [
31
+                {type: 'html'},
32
+                {type: 'text-summary'}
33
+            ]
34
+        },
35
+        reporters: ['progress', 'kjhtml'],
36
+        port: 9876,
37
+        colors: true,
38
+        logLevel: config.LOG_INFO,
39
+        autoWatch: true,
40
+        browsers: ['Chrome'],
41
+        singleRun: false,
42
+        restartOnFileChange: true
43
+    });
44
+};

+ 13403
- 0
package-lock.json
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 60
- 0
package.json Visa fil

@@ -0,0 +1,60 @@
1
+{
2
+    "name": "ultima",
3
+    "version": "12.2.0-SNAPSHOT",
4
+    "license": "COMMERCIAL",
5
+    "angular-cli": {},
6
+    "scripts": {
7
+        "ng": "ng",
8
+        "start": "ng serve",
9
+        "build": "ng build",
10
+        "test": "ng test",
11
+        "lint": "ng lint",
12
+        "e2e": "ng e2e"
13
+    },
14
+    "private": true,
15
+    "dependencies": {
16
+        "@angular/animations": "~12.0.0",
17
+        "@angular/cdk": "~12.0.0",
18
+        "@angular/common": "~12.0.0",
19
+        "@angular/compiler": "~12.0.0",
20
+        "@angular/core": "~12.0.0",
21
+        "@angular/forms": "~12.0.0",
22
+        "@angular/platform-browser": "~12.0.0",
23
+        "@angular/platform-browser-dynamic": "~12.0.0",
24
+        "@angular/router": "~12.0.0",
25
+        "@fullcalendar/angular": "^5.8.0",
26
+        "@fullcalendar/core": "^5.8.0",
27
+        "@fullcalendar/daygrid": "^5.8.0",
28
+        "@fullcalendar/interaction": "^5.8.0",
29
+        "@fullcalendar/timegrid": "^5.8.0",
30
+        "chart.js": "^3.3.2",
31
+        "primeflex": "3.0.1",
32
+        "primeicons": "4.1.0",
33
+        "primeng": "12.2.1",
34
+        "prismjs": "1.9.0",
35
+        "rxjs": "~6.6.0",
36
+        "tslib": "^2.0.0",
37
+        "web-animations-js": "^2.3.2",
38
+        "zone.js": "~0.11.4"
39
+    },
40
+    "devDependencies": {
41
+        "@angular-devkit/build-angular": "~12.0.0",
42
+        "@angular/cli": "~12.0.0",
43
+        "@angular/compiler-cli": "~12.0.0",
44
+        "@types/jasmine": "~3.6.0",
45
+        "@types/jasminewd2": "~2.0.8",
46
+        "@types/node": "^12.11.1",
47
+        "codelyzer": "^6.0.0",
48
+        "jasmine-core": "~3.6.0",
49
+        "jasmine-spec-reporter": "~5.0.0",
50
+        "karma": "~5.1.0",
51
+        "karma-chrome-launcher": "~3.1.0",
52
+        "karma-coverage-istanbul-reporter": "~3.0.3",
53
+        "karma-jasmine": "~4.0.0",
54
+        "karma-jasmine-html-reporter": "^1.5.0",
55
+        "protractor": "~7.0.0",
56
+        "ts-node": "~8.3.0",
57
+        "tslint": "~6.1.0",
58
+        "typescript": "~4.2.3"
59
+    }
60
+}

+ 28
- 0
src/app/app-routing.module.ts Visa fil

@@ -0,0 +1,28 @@
1
+import { NgModule } from '@angular/core';
2
+import { RouterModule, Routes } from '@angular/router';
3
+import { AppMainComponent } from './app.main.component';
4
+
5
+export const appRouteList: Routes = [
6
+    {
7
+        path: 'app', component: AppMainComponent,
8
+        loadChildren: () => import('./pages/pages.routing.module').then(m => m.PagesRoutingModule)
9
+    },
10
+    {
11
+        path: '**',
12
+        redirectTo: 'app/dashboard/dashboard'
13
+    }
14
+];
15
+
16
+@NgModule({
17
+    exports: [
18
+        RouterModule
19
+    ],
20
+    imports: [
21
+        RouterModule.forRoot(appRouteList, {
22
+            scrollPositionRestoration: 'enabled', // Add options right here
23
+            relativeLinkResolution: 'legacy'
24
+        })
25
+    ]
26
+})
27
+export class AppRoutingModule {
28
+}

+ 3
- 0
src/app/app.breadcrumb.component.html Visa fil

@@ -0,0 +1,3 @@
1
+<div class="layout-breadcrumb-container flex justify-content-between align-items-center shadow-1">
2
+    <p-breadcrumb [model]="items" [home]="home" styleClass="layout-breadcrumb pl-4 py-2"></p-breadcrumb>
3
+</div>

+ 31
- 0
src/app/app.breadcrumb.component.ts Visa fil

@@ -0,0 +1,31 @@
1
+import { Component, OnDestroy } from '@angular/core';
2
+import { AppBreadcrumbService } from './app.breadcrumb.service';
3
+import { Subscription } from 'rxjs';
4
+import { MenuItem } from 'primeng/api';
5
+
6
+@Component({
7
+    selector: 'app-breadcrumb',
8
+    templateUrl: './app.breadcrumb.component.html'
9
+})
10
+export class AppBreadcrumbComponent implements OnDestroy {
11
+
12
+    subscription: Subscription;
13
+
14
+    items: MenuItem[];
15
+
16
+    home: MenuItem;
17
+
18
+    constructor(public breadcrumbService: AppBreadcrumbService) {
19
+        this.subscription = breadcrumbService.itemsHandler.subscribe(response => {
20
+            this.items = response;
21
+        });
22
+
23
+        this.home = { icon: 'pi pi-home', routerLink: '/' };
24
+    }
25
+
26
+    ngOnDestroy() {
27
+        if (this.subscription) {
28
+            this.subscription.unsubscribe();
29
+        }
30
+    }
31
+}

+ 15
- 0
src/app/app.breadcrumb.service.ts Visa fil

@@ -0,0 +1,15 @@
1
+import { Injectable } from '@angular/core';
2
+import { Subject ,  Observable } from 'rxjs';
3
+import { MenuItem } from 'primeng/api';
4
+
5
+@Injectable()
6
+export class AppBreadcrumbService {
7
+
8
+    private itemsSource = new Subject<MenuItem[]>();
9
+
10
+    itemsHandler = this.itemsSource.asObservable();
11
+
12
+    setItems(items: MenuItem[]) {
13
+        this.itemsSource.next(items);
14
+    }
15
+}

+ 68
- 0
src/app/app.code.component.scss Visa fil

@@ -0,0 +1,68 @@
1
+.flex > div,
2
+.box {
3
+	background-color: var(--surface-e);
4
+	text-align: center;
5
+	padding: 1rem;
6
+	border-radius: 4px;
7
+	box-shadow: 0 2px 1px -1px rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 1px 3px 0 rgba(0,0,0,.12);
8
+}
9
+
10
+.flex > div {
11
+	width: 8rem;
12
+}
13
+
14
+i:not([class~="pi"]) {
15
+	background-color: var(--surface-b);
16
+	color: var(--primary-color);
17
+	font-family: Monaco, courier, monospace;
18
+	font-style: normal;
19
+	font-size: 12px;
20
+	padding: 2px 4px;
21
+	letter-spacing: .5px;
22
+	border-radius: 3px;
23
+	font-weight: 600;
24
+	margin: 0 2px;
25
+}
26
+
27
+:host ::ng-deep pre[class*="language-"] {
28
+	box-shadow: none;
29
+	border: 0 none;
30
+
31
+	&:before, &:after {
32
+		display: none !important;
33
+	}
34
+
35
+	code {
36
+		border-left: 10px solid var(--surface-d) !important;
37
+		box-shadow: none !important;
38
+		background: var(--surface-b) !important;
39
+		margin: 1em 0;
40
+		color: var(--text-color);
41
+		font-size: 14px;
42
+
43
+		.token {
44
+			&.tag,
45
+			&.keyword {
46
+				color: #2196F3 !important;
47
+			}
48
+
49
+			&.attr-name,
50
+			&.attr-string {
51
+				color: #2196F3 !important;
52
+			}
53
+
54
+			&.attr-value {
55
+				color: #4CAF50 !important;
56
+			}
57
+
58
+			&.punctuation {
59
+				color: var(--text-color);
60
+			}
61
+
62
+			&.operator,
63
+			&.string {
64
+				background: transparent;
65
+			}
66
+		}
67
+	}
68
+}

+ 32
- 0
src/app/app.code.component.ts Visa fil

@@ -0,0 +1,32 @@
1
+import { Component, ElementRef, AfterViewInit, Input, NgModule, ViewChild } from '@angular/core';
2
+import { CommonModule } from '@angular/common';
3
+
4
+@Component({
5
+    selector: 'app-code',
6
+    template: `
7
+        <pre [ngClass]="'language-' + lang"><code #code><ng-content></ng-content>
8
+</code></pre>
9
+    `,
10
+    styleUrls: ['./app.code.component.scss']
11
+})
12
+export class AppCodeComponent implements AfterViewInit {
13
+
14
+    @Input() lang = 'markup';
15
+
16
+    @ViewChild('code') codeViewChild: ElementRef;
17
+
18
+    constructor(public el: ElementRef) { }
19
+
20
+    ngAfterViewInit() {
21
+        if (window['Prism']) {
22
+            window['Prism'].highlightElement(this.codeViewChild.nativeElement);
23
+        }
24
+    }
25
+}
26
+
27
+@NgModule({
28
+    imports: [CommonModule],
29
+    exports: [AppCodeComponent],
30
+    declarations: [AppCodeComponent]
31
+})
32
+export class AppCodeModule { }

+ 1
- 0
src/app/app.component.html Visa fil

@@ -0,0 +1 @@
1
+<router-outlet></router-outlet>

+ 0
- 0
src/app/app.component.scss Visa fil


+ 31
- 0
src/app/app.component.spec.ts Visa fil

@@ -0,0 +1,31 @@
1
+/* tslint:disable:no-unused-variable */
2
+
3
+import { TestBed, async } from '@angular/core/testing';
4
+import { RouterTestingModule } from '@angular/router/testing';
5
+import { AppComponent } from './app.component';
6
+import { AppTopBarComponent } from './app.topbar.component';
7
+import { AppFooterComponent } from './app.footer.component';
8
+import { AppMenuComponent } from './app.menu.component';
9
+import { ProgressBarModule} from 'primeng/progressbar';
10
+import { MenuService } from './app.menu.service';
11
+
12
+describe('AppComponent', () => {
13
+    beforeEach(() => {
14
+        TestBed.configureTestingModule({
15
+            imports: [ RouterTestingModule, ProgressBarModule ],
16
+            declarations: [ AppComponent,
17
+                AppMenuComponent,
18
+                AppTopBarComponent,
19
+                AppFooterComponent
20
+            ],
21
+            providers: [MenuService]
22
+        });
23
+        TestBed.compileComponents();
24
+    });
25
+
26
+    it('should create the app', async(() => {
27
+        const fixture = TestBed.createComponent(AppComponent);
28
+        const app = fixture.debugElement.componentInstance;
29
+        expect(app).toBeTruthy();
30
+    }));
31
+});

+ 32
- 0
src/app/app.component.ts Visa fil

@@ -0,0 +1,32 @@
1
+import {Component, OnInit} from '@angular/core';
2
+import { PrimeNGConfig } from 'primeng/api';
3
+
4
+@Component({
5
+    selector: 'app-root',
6
+    templateUrl: './app.component.html',
7
+    styleUrls: ['./app.component.scss']
8
+})
9
+export class AppComponent implements OnInit{
10
+
11
+    topbarTheme = 'grey';
12
+
13
+    menuTheme = 'light';
14
+
15
+    layoutMode = 'light';
16
+
17
+    menuMode = 'static';
18
+
19
+    inlineMenuPosition = 'bottom';
20
+
21
+    inputStyle = 'filled';
22
+
23
+    ripple = true;
24
+
25
+    isRTL = false;
26
+
27
+    constructor(private primengConfig: PrimeNGConfig) {}
28
+
29
+    ngOnInit() {
30
+        this.primengConfig.ripple = true;
31
+    }
32
+}

+ 339
- 0
src/app/app.config.component.ts Visa fil

@@ -0,0 +1,339 @@
1
+import {Component, OnInit, ViewChild} from '@angular/core';
2
+import { AppComponent } from './app.component';
3
+import { AppMainComponent } from './app.main.component';
4
+
5
+@Component({
6
+    selector: 'app-config',
7
+    template: `
8
+        <p-sidebar #sidebar [(visible)]="configActive" [position]="app.isRTL ? 'left' : 'right'" [blockScroll]="true" [showCloseIcon]="false" [baseZIndex]="1000" styleClass="layout-config p-sidebar-sm fs-small p-0">
9
+            <div class="layout-config-panel flex flex-column">
10
+                <div class="px-3 pt-3">
11
+                    <h5>Theme Customization</h5>
12
+                    <span>Ultima offers different themes for layout, topbar, menu etc.</span>
13
+                </div>
14
+
15
+                <hr class="mb-0" />
16
+
17
+                <div class="layout-config-options p-3">
18
+                    <h6>Layout/Theme Scale</h6>
19
+                    <div class="flex align-items-center">
20
+                        <button pButton pRipple type="button" icon="pi pi-minus" (click)="decrementScale()" class="p-button-rounded p-button-text" [disabled]="scale === scales[0]"></button>
21
+                        <i class="pi pi-circle-on m-1 scale-icon" *ngFor="let s of scales" [ngClass]="{'scale-active': s === scale}"></i>
22
+                        <button pButton pRipple type="button" icon="pi pi-plus" (click)="incrementScale()" class="p-button-rounded p-button-text" [disabled]="scale === scales[scales.length - 1]"></button>
23
+                    </div>
24
+
25
+                    <h6>Layout Mode</h6>
26
+                    <div class="flex">
27
+                        <div class="flex align-items-center">
28
+                            <p-radioButton name="layoutMode" value="light" [(ngModel)]="app.layoutMode" inputId="layoutMode1" (onClick)="onLayoutModeChange($event, 'light')"></p-radioButton>
29
+                            <label for="layoutMode1" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Light</label>
30
+                        </div>
31
+                        <div class="flex align-items-center" [ngClass]="{'ml-4': !app.isRTL, 'mr-4': app.isRTL}">
32
+                            <p-radioButton name="layoutMode" value="dark" [(ngModel)]="app.layoutMode" inputId="layoutMode2" (onClick)="onLayoutModeChange($event, 'dark')"></p-radioButton>
33
+                            <label for="layoutMode2" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Dark</label>
34
+                        </div>
35
+                    </div>
36
+
37
+                    <h6>Menu Mode</h6>
38
+                    <div class="flex">
39
+                        <div class="flex flex-column">
40
+                            <div class="flex align-items-center">
41
+                                <p-radioButton name="menuMode" value="static" [(ngModel)]="app.menuMode" inputId="menuMode1"></p-radioButton>
42
+                                <label for="menuMode1" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Static</label>
43
+                            </div>
44
+                            <div class="flex align-items-center mt-3">
45
+                                <p-radioButton name="menuMode" value="horizontal" [(ngModel)]="app.menuMode" inputId="menuMode2"></p-radioButton>
46
+                                <label for="menuMode2" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Horizontal</label>
47
+                            </div>
48
+                        </div>
49
+                        <div class="flex flex-column" [ngClass]="{'ml-4': !app.isRTL, 'mr-4': app.isRTL}">
50
+                            <div class="flex align-items-center">
51
+                                <p-radioButton name="menuMode" value="overlay" [(ngModel)]="app.menuMode" inputId="menuMode4"></p-radioButton>
52
+                                <label for="menuMode4" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Overlay</label>
53
+                            </div>
54
+                            <div class="flex align-items-center mt-3">
55
+                                <p-radioButton name="menuMode" value="slim" [(ngModel)]="app.menuMode" inputId="menuMode3"></p-radioButton>
56
+                                <label for="menuMode3" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Slim</label>
57
+                            </div>
58
+                        </div>
59
+                    </div>
60
+
61
+                    <h6>Inline Menu Position</h6>
62
+                    <div class="flex">
63
+                        <div class="flex align-items-center">
64
+                            <p-radioButton name="inlineMenuPosition" value="top" [(ngModel)]="app.inlineMenuPosition" inputId="inlineMenuPosition1"></p-radioButton>
65
+                            <label for="inlineMenuPosition1" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Top</label>
66
+                        </div>
67
+                        <div class="flex align-items-center" [ngClass]="{'ml-4': !app.isRTL, 'mr-4': app.isRTL}">
68
+                            <p-radioButton name="inlineMenuPosition" value="bottom" [(ngModel)]="app.inlineMenuPosition" inputId="inlineMenuPosition2"></p-radioButton>
69
+                            <label for="inlineMenuPosition2" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Bottom</label>
70
+                        </div>
71
+                        <div class="flex align-items-center" [ngClass]="{'ml-4': !app.isRTL, 'mr-4': app.isRTL}">
72
+                            <p-radioButton name="inlineMenuPosition" value="both" [(ngModel)]="app.inlineMenuPosition" inputId="inlineMenuPosition3"></p-radioButton>
73
+                            <label for="inlineMenuPosition3" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Both</label>
74
+                        </div>
75
+                    </div>
76
+
77
+                    <h6>Input Background</h6>
78
+                    <div class="flex">
79
+                        <div class="flex align-items-center">
80
+                            <p-radioButton name="inputStyle" value="outlined" [(ngModel)]="app.inputStyle" inputId="inputStyle1" (onClick)="onInputStyleClick()"></p-radioButton>
81
+                            <label for="inputStyle1" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Outlined</label>
82
+                        </div>
83
+                        <div class="flex align-items-center" [ngClass]="{'ml-4': !app.isRTL, 'mr-4': app.isRTL}">
84
+                            <p-radioButton name="inputStyle" value="filled" [(ngModel)]="app.inputStyle" inputId="inputStyle2" (onClick)="onInputStyleClick()"></p-radioButton>
85
+                            <label for="inputStyle2" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">Filled</label>
86
+                        </div>
87
+                    </div>
88
+
89
+                    <h6>Ripple Effect</h6>
90
+                    <p-inputSwitch [ngModel]="app.ripple" (onChange)="appMain.onRippleChange($event)"></p-inputSwitch>
91
+
92
+                    <h6>RTL</h6>
93
+                    <p-inputSwitch [ngModel]="app.isRTL" (onChange)="appMain.onRTLChange($event)" styleClass="block"></p-inputSwitch>
94
+
95
+                    <h6>Menu Themes</h6>
96
+                    <div *ngIf="app.layoutMode!=='dark'" class="grid">
97
+                        <div *ngFor="let t of menuThemes" class="col col-fixed">
98
+                            <a style="cursor: pointer" (click)="changeMenuTheme(t)" class="layout-config-color-option" [title]="t.name">
99
+                                <span class="color" [ngStyle]="{'background-color': t.color}"></span>
100
+                                <span class="check flex align-items-center justify-content-center" *ngIf="app.menuTheme === t.name">
101
+                                    <i class="pi pi-check" style="color: var(--menu-text-color)"></i>
102
+                                </span>
103
+                            </a>
104
+                        </div>
105
+                    </div>
106
+                    <p *ngIf="app.layoutMode==='dark'">Menu themes are only available in light mode by design as large surfaces can emit too much brightness in dark mode.</p>
107
+
108
+                    <h6>Topbar Themes</h6>
109
+                    <div class="grid">
110
+                        <div *ngFor="let t of topbarThemes" class="col col-fixed">
111
+                            <a style="cursor: pointer" (click)="changeTopbarTheme(t)" class="layout-config-color-option" [title]="t.name">
112
+                                <span class="color" [ngStyle]="{'background-color': t.color}"></span>
113
+                                <span class="check flex align-items-center justify-content-center" *ngIf="app.topbarTheme === t.name">
114
+                                    <i class="pi pi-check" style="color: var(--topbar-text-color)"></i>
115
+                                </span>
116
+                            </a>
117
+                        </div>
118
+                    </div>
119
+
120
+                    <h6>Component Themes</h6>
121
+                    <div class="grid">
122
+                        <div *ngFor="let t of themes" class="col col-fixed">
123
+                            <a style="cursor: pointer" (click)="changeTheme(t.name)" class="layout-config-color-option" [title]="t.name">
124
+                                <span class="color" [ngStyle]="{'background-color': t.color}"></span>
125
+                                <span class="check flex align-items-center justify-content-center" *ngIf="theme === t.name">
126
+                                    <i class="pi pi-check" style="color: var(--primary-color-text)"></i>
127
+                                </span>
128
+                            </a>
129
+                        </div>
130
+                    </div>
131
+                </div>
132
+            </div>
133
+        </p-sidebar>
134
+
135
+        <p-button type="button" (click)="configActive = true" icon="pi pi-cog" *ngIf="!configActive" styleClass="layout-config-button"></p-button>
136
+    `
137
+})
138
+export class AppConfigComponent implements OnInit {
139
+
140
+    scale = 14;
141
+
142
+    scales: number[] = [12, 13, 14, 15, 16];
143
+
144
+    themes: any[];
145
+
146
+    menuThemes: any[];
147
+
148
+    menuTheme = 'light';
149
+
150
+    topbarThemes: any[];
151
+
152
+    topbarTheme = 'blue';
153
+
154
+    theme = 'indigo';
155
+
156
+    matchingMenuTheme = false;
157
+
158
+    matchingTopbarTheme = false;
159
+
160
+    selectedMenuTheme: any;
161
+
162
+    selectedTopbarTheme: any;
163
+
164
+    configActive = false;
165
+
166
+    isInputBackgroundChanged = false;
167
+
168
+    constructor(public appMain: AppMainComponent, public app: AppComponent) {}
169
+
170
+    ngOnInit() {
171
+        this.themes = [
172
+            {name: 'indigo', color: '#3F51B5'},
173
+            {name: 'pink', color: '#E91E63'},
174
+            {name: 'purple', color: '#9C27B0'},
175
+            {name: 'deeppurple', color: '#673AB7'},
176
+            {name: 'blue', color: '#2196F3'},
177
+            {name: 'lightblue', color: '#03A9F4'},
178
+            {name: 'cyan', color: '#00BCD4'},
179
+            {name: 'teal', color: '#009688'},
180
+            {name: 'green', color: '#4CAF50'},
181
+            {name: 'lightgreen', color: '#8BC34A'},
182
+            {name: 'lime', color: '#CDDC39'},
183
+            {name: 'yellow', color: '#FFEB3B'},
184
+            {name: 'amber', color: '#FFC107'},
185
+            {name: 'orange', color: '#FF9800'},
186
+            {name: 'deeporange', color: '#FF5722'},
187
+            {name: 'brown', color: '#795548'},
188
+            {name: 'bluegrey', color: '#607D8B'}
189
+        ];
190
+
191
+        this.menuThemes = [
192
+            {name: 'light', color: '#FDFEFF'},
193
+            {name: 'dark', color: '#434B54'},
194
+            {name: 'indigo', color: '#1A237E'},
195
+            {name: 'bluegrey', color: '#37474F'},
196
+            {name: 'brown', color: '#4E342E'},
197
+            {name: 'cyan', color: '#006064'},
198
+            {name: 'green', color: '#2E7D32'},
199
+            {name: 'deeppurple', color: '#4527A0'},
200
+            {name: 'deeporange', color: '#BF360C'},
201
+            {name: 'pink', color: '#880E4F'},
202
+            {name: 'purple', color: '#6A1B9A'},
203
+            {name: 'teal', color: '#00695C'}
204
+        ];
205
+
206
+        this.topbarThemes = [
207
+            {name: 'lightblue', color: '#2E88FF'},
208
+            {name: 'dark', color: '#363636'},
209
+            {name: 'white', color: '#FDFEFF'},
210
+            {name: 'blue', color: '#1565C0'},
211
+            {name: 'deeppurple', color: '#4527A0'},
212
+            {name: 'purple', color: '#6A1B9A'},
213
+            {name: 'pink', color: '#AD1457'},
214
+            {name: 'cyan', color: '#0097A7'},
215
+            {name: 'teal', color: '#00796B'},
216
+            {name: 'green', color: '#43A047'},
217
+            {name: 'lightgreen', color: '#689F38'},
218
+            {name: 'lime', color: '#AFB42B'},
219
+            {name: 'yellow', color: '#FBC02D'},
220
+            {name: 'amber', color: '#FFA000'},
221
+            {name: 'orange', color: '#FB8C00'},
222
+            {name: 'deeporange', color: '#D84315'},
223
+            {name: 'brown', color: '#5D4037'},
224
+            {name: 'grey', color: '#616161'},
225
+            {name: 'bluegrey', color: '#546E7A'},
226
+            {name: 'indigo', color: '#3F51B5'}
227
+        ];
228
+
229
+        this.selectedMenuTheme = this.menuThemes.find(theme => theme.name === this.menuTheme);
230
+        this.selectedTopbarTheme = this.topbarThemes.find(theme => theme.name === this.topbarTheme);
231
+    }
232
+
233
+    decrementScale() {
234
+        this.scale--;
235
+        this.applyScale();
236
+    }
237
+
238
+    incrementScale() {
239
+        this.scale++;
240
+        this.applyScale();
241
+    }
242
+
243
+    applyScale() {
244
+        document.documentElement.style.fontSize = this.scale + 'px';
245
+    }
246
+
247
+    onInputStyleClick() {
248
+        this.isInputBackgroundChanged = true;
249
+    }
250
+
251
+    onLayoutModeChange(event, mode) {
252
+        const appLogoLink: HTMLImageElement = document.getElementById('app-logo') as HTMLImageElement;
253
+        this.app.layoutMode = mode;
254
+
255
+        if (!this.isInputBackgroundChanged) {
256
+            this.app.inputStyle = mode === 'dark' ? 'filled' : 'outlined';
257
+        }
258
+
259
+        if (mode === 'dark') {
260
+            this.app.menuTheme = 'dark';
261
+            this.app.topbarTheme = 'dark';
262
+            appLogoLink.src = 'assets/layout/images/logo-light.png';
263
+        }
264
+        else {
265
+            this.app.menuTheme = 'light';
266
+            this.app.topbarTheme = 'blue';
267
+            appLogoLink.src = 'assets/layout/images/logo-light.png';
268
+        }
269
+
270
+        const layoutLink: HTMLLinkElement = document.getElementById('layout-css') as HTMLLinkElement;
271
+        const layoutHref = 'assets/layout/css/layout-' + this.app.layoutMode + '.css';
272
+        this.replaceLink(layoutLink, layoutHref);
273
+
274
+        const themeLink = document.getElementById('theme-css');
275
+        const urlTokens = themeLink.getAttribute('href').split('/');
276
+        urlTokens[urlTokens.length - 1] = 'theme-' + this.app.layoutMode + '.css';
277
+        const newURL = urlTokens.join('/');
278
+
279
+        this.replaceLink(themeLink, newURL, this.appMain['refreshChart']);
280
+    }
281
+
282
+    changeTheme(theme) {
283
+        this.theme = theme;
284
+
285
+        const themeLink: HTMLLinkElement = document.getElementById('theme-css') as HTMLLinkElement;
286
+        const themeHref = 'assets/theme/' + theme + '/theme-' + this.app.layoutMode + '.css';
287
+        this.replaceLink(themeLink, themeHref);
288
+    }
289
+
290
+    changeMenuTheme(theme) {
291
+        this.selectedMenuTheme = theme;
292
+        this.app.menuTheme = theme.name;
293
+    }
294
+
295
+    changeTopbarTheme(theme) {
296
+        this.selectedTopbarTheme = theme;
297
+        this.app.topbarTheme = theme.name;
298
+
299
+        const appLogoLink: HTMLImageElement = document.getElementById('app-logo') as HTMLImageElement;
300
+
301
+        if (theme.name === 'white' || theme.name === 'yellow' || theme.name === 'amber'
302
+            || theme.name === 'orange' || theme.name === 'lime') {
303
+            appLogoLink.src = 'assets/layout/images/logo-dark.png';
304
+        }
305
+        else {
306
+            appLogoLink.src = 'assets/layout/images/logo-light.png';
307
+        }
308
+    }
309
+
310
+    isIE() {
311
+        return /(MSIE|Trident\/|Edge\/)/i.test(window.navigator.userAgent);
312
+    }
313
+
314
+    replaceLink(linkElement, href, callback?) {
315
+        if (this.isIE()) {
316
+            linkElement.setAttribute('href', href);
317
+            if (callback) {
318
+                callback();
319
+            }
320
+        } else {
321
+            const id = linkElement.getAttribute('id');
322
+            const cloneLinkElement = linkElement.cloneNode(true);
323
+
324
+            cloneLinkElement.setAttribute('href', href);
325
+            cloneLinkElement.setAttribute('id', id + '-clone');
326
+
327
+            linkElement.parentNode.insertBefore(cloneLinkElement, linkElement.nextSibling);
328
+
329
+            cloneLinkElement.addEventListener('load', () => {
330
+                linkElement.remove();
331
+                cloneLinkElement.setAttribute('id', id);
332
+
333
+                if (callback) {
334
+                    callback();
335
+                }
336
+            });
337
+        }
338
+    }
339
+}

+ 17
- 0
src/app/app.footer.component.ts Visa fil

@@ -0,0 +1,17 @@
1
+import {Component} from '@angular/core';
2
+import {AppComponent} from './app.component';
3
+
4
+@Component({
5
+    selector: 'app-footer',
6
+    template: `
7
+        <div class="layout-footer flex align-items-center p-4 shadow-2">
8
+            <img style="height: 2.25rem" id="footer-logo" [src]="'assets/layout/images/logo-' + (app.layoutMode === 'light' ? 'dark' : 'light') + '.png'" alt="ultima-footer-logo">
9
+            <button pButton pRipple type="button" icon="pi pi-github fs-large" class="p-button-rounded p-button-text p-button-plain" [ngClass]="{'ml-auto mr-2': !app.isRTL, 'ml-2 mr-auto': app.isRTL}"></button>
10
+            <button pButton pRipple type="button" icon="pi pi-facebook fs-large" class="p-button-rounded p-button-text p-button-plain" [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}"></button>
11
+            <button pButton pRipple type="button" icon="pi pi-twitter fs-large" class="p-button-rounded p-button-text p-button-plain" [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}"></button>
12
+        </div>
13
+    `
14
+})
15
+export class AppFooterComponent {
16
+    constructor(public app: AppComponent) {}
17
+}

+ 20
- 0
src/app/app.inlinemenu.component.html Visa fil

@@ -0,0 +1,20 @@
1
+<div [ngClass]="{'layout-inline-menu': true, 'layout-inline-menu-active':appMain.inlineMenuActive[key]}" [ngStyle]="style" [class]="styleClass">
2
+    <a class="layout-inline-menu-action flex flex-row align-items-center" [ngClass]="appMain.isHorizontal() ? 'p-3 lg:col-1 py-3' : 'p-3'" (click)="onClick($event)"
3
+        pTooltip="Alex Ondoa" [tooltipDisabled]="isTooltipDisabled">
4
+        <img src="assets/demo/images/avatar/amyelsner.png" alt="avatar" style="width: 32px; height: 32px;">
5
+        <span class="flex flex-column" [ngClass]="{'ml-2': !app.isRTL, 'mr-2': app.isRTL}">
6
+            <span class="font-bold">Alex Ondoa</span>
7
+            <small>Developpeur</small>
8
+        </span>
9
+        <i class="layout-inline-menu-icon pi pi-angle-down" [ngClass]="{'ml-auto': !app.isRTL, 'mr-auto': app.isRTL}"></i>
10
+    </a>
11
+
12
+    <ul class="layout-inline-menu-action-panel" [@menu]="appMain.inlineMenuActive[key] ? isHorizontalActive() ? 'visible' : 'visibleAnimated' : isHorizontalActive() ? 'hidden' : 'hiddenAnimated'">
13
+        <li class="layout-inline-menu-action-item" pTooltip="Logout" [tooltipDisabled]="isTooltipDisabled">
14
+            <a class="flex flex-row align-items-center" [attr.tabindex]="tabIndex">
15
+                <i class="pi pi-power-off pi-fw"></i>
16
+                <span>Logout</span>
17
+            </a>
18
+        </li>
19
+    </ul>
20
+</div>

+ 63
- 0
src/app/app.inlinemenu.component.ts Visa fil

@@ -0,0 +1,63 @@
1
+import { Component, Input } from '@angular/core';
2
+import { trigger, state, transition, style, animate } from '@angular/animations';
3
+import { AppMainComponent } from './app.main.component';
4
+import { AppComponent } from './app.component';
5
+
6
+@Component({
7
+    selector: 'app-inline-menu',
8
+    templateUrl: './app.inlinemenu.component.html',
9
+    animations: [
10
+        trigger('menu', [
11
+            state('hiddenAnimated', style({
12
+                height: '0px',
13
+                paddingBottom: '0px',
14
+                overflow: 'hidden'
15
+            })),
16
+            state('visibleAnimated', style({
17
+                height: '*',
18
+                overflow: 'visible'
19
+            })),
20
+            state('visible', style({
21
+                opacity: 1,
22
+                'z-index': 100
23
+            })),
24
+            state('hidden', style({
25
+                opacity: 0,
26
+                'z-index': '*'
27
+            })),
28
+            transition('visibleAnimated => hiddenAnimated', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')),
29
+            transition('hiddenAnimated => visibleAnimated', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')),
30
+            transition('visible => hidden', animate('.1s linear')),
31
+            transition('hidden => visible', [style({transform: 'scaleY(0.8)'}), animate('.12s cubic-bezier(0, 0, 0.2, 1)')])
32
+        ])
33
+    ]
34
+})
35
+export class AppInlineMenuComponent {
36
+
37
+    @Input() key = 'inline-menu';
38
+
39
+    @Input() style: any;
40
+
41
+    @Input() styleClass: string;
42
+
43
+    active: boolean;
44
+
45
+    constructor(public appMain: AppMainComponent, public app: AppComponent) { }
46
+
47
+    onClick(event) {
48
+        this.appMain.onInlineMenuClick(event, this.key);
49
+        event.preventDefault();
50
+    }
51
+
52
+    get isTooltipDisabled() {
53
+        return !(this.appMain.isSlim() && !this.appMain.isMobile());
54
+    }
55
+
56
+    get tabIndex() {
57
+        return !this.appMain.inlineMenuActive  ? '-1' : null;
58
+    }
59
+
60
+    isHorizontalActive() {
61
+       return this.appMain.isHorizontal() && !this.appMain.isMobile();
62
+    }
63
+}

+ 38
- 0
src/app/app.main.component.html Visa fil

@@ -0,0 +1,38 @@
1
+<div class="layout-wrapper" [ngClass]="{'p-input-filled': app.inputStyle === 'filled', 'p-ripple-disabled': !app.ripple,
2
+        'layout-menu-static': isStatic(),
3
+        'layout-menu-overlay': isOverlay(),
4
+        'layout-menu-horizontal': isHorizontal(),
5
+        'layout-menu-slim': isSlim(),
6
+        'layout-menu-active': menuActive,
7
+        'layout-menu-mobile-active': mobileMenuActive,
8
+        'layout-topbar-mobile-active': mobileTopbarActive,
9
+        'layout-rightmenu-active': rightMenuActive,
10
+        'layout-rtl': app.isRTL}" [class]="'layout-menu-' + app.menuTheme + ' layout-topbar-' + app.topbarTheme">
11
+
12
+    <app-topbar></app-topbar>
13
+
14
+    <app-rightmenu></app-rightmenu>
15
+
16
+    <div class="menu-wrapper" (click)="onMenuClick($event)">
17
+        <div class="layout-menu-container">
18
+            <app-inline-menu *ngIf="app.inlineMenuPosition=='top' || app.inlineMenuPosition=='both'" key="top"></app-inline-menu>
19
+            <app-menu></app-menu>
20
+            <app-inline-menu *ngIf="app.inlineMenuPosition=='bottom' || app.inlineMenuPosition=='both'" key="bottom"></app-inline-menu>
21
+        </div>
22
+    </div>
23
+
24
+    <div class="layout-main">
25
+        <app-breadcrumb></app-breadcrumb>
26
+
27
+        <div class="layout-content">
28
+            <router-outlet></router-outlet>
29
+        </div>
30
+
31
+        <app-footer></app-footer>
32
+    </div>
33
+
34
+    <app-config></app-config>
35
+
36
+    <div *ngIf="mobileMenuActive" class="layout-mask modal-in"></div>
37
+
38
+</div>

+ 238
- 0
src/app/app.main.component.ts Visa fil

@@ -0,0 +1,238 @@
1
+import {Component, AfterViewInit, Renderer2, OnInit, OnDestroy} from '@angular/core';
2
+import { MenuService } from './app.menu.service';
3
+import { PrimeNGConfig } from 'primeng/api';
4
+import { AppComponent } from './app.component';
5
+
6
+@Component({
7
+    selector: 'app-main',
8
+    templateUrl: './app.main.component.html'
9
+})
10
+export class AppMainComponent implements AfterViewInit, OnInit, OnDestroy {
11
+
12
+    topbarMenuActive: boolean;
13
+
14
+    menuActive: boolean;
15
+
16
+    staticMenuDesktopInactive: boolean;
17
+
18
+    mobileMenuActive: boolean;
19
+
20
+    menuClick: boolean;
21
+
22
+    mobileTopbarActive: boolean;
23
+
24
+    topbarRightClick: boolean;
25
+
26
+    topbarItemClick: boolean;
27
+
28
+    activeTopbarItem: string;
29
+
30
+    documentClickListener: () => void;
31
+
32
+    configActive: boolean;
33
+
34
+    configClick: boolean;
35
+
36
+    rightMenuActive: boolean;
37
+
38
+    menuHoverActive = false;
39
+
40
+    searchClick = false;
41
+
42
+    search = false;
43
+
44
+    currentInlineMenuKey: string;
45
+
46
+    inlineMenuActive: any[] = [];
47
+
48
+    inlineMenuClick: boolean;
49
+
50
+    constructor(public renderer: Renderer2, private menuService: MenuService, private primengConfig: PrimeNGConfig,
51
+                public app: AppComponent) { }
52
+
53
+    ngOnInit() {
54
+        this.menuActive = this.isStatic() && !this.isMobile();
55
+    }
56
+
57
+    ngAfterViewInit() {
58
+        // hides the horizontal submenus or top menu if outside is clicked
59
+        this.documentClickListener = this.renderer.listen('body', 'click', () => {
60
+            if (!this.topbarItemClick) {
61
+                this.activeTopbarItem = null;
62
+                this.topbarMenuActive = false;
63
+            }
64
+
65
+            if (!this.menuClick && (this.isHorizontal() || this.isSlim())) {
66
+                this.menuService.reset();
67
+            }
68
+
69
+            if (this.configActive && !this.configClick) {
70
+                this.configActive = false;
71
+            }
72
+
73
+            if (!this.menuClick) {
74
+                if (this.mobileMenuActive) {
75
+                    this.mobileMenuActive = false;
76
+                }
77
+
78
+                if (this.isOverlay()) {
79
+                    this.menuActive = false;
80
+                }
81
+
82
+                this.menuHoverActive = false;
83
+                this.unblockBodyScroll();
84
+            }
85
+
86
+            if (!this.searchClick) {
87
+                this.search = false;
88
+            }
89
+
90
+            if (this.inlineMenuActive[this.currentInlineMenuKey] && !this.inlineMenuClick) {
91
+                this.inlineMenuActive[this.currentInlineMenuKey] = false;
92
+            }
93
+
94
+            this.inlineMenuClick = false;
95
+            this.searchClick = false;
96
+            this.configClick = false;
97
+            this.topbarItemClick = false;
98
+            this.topbarRightClick = false;
99
+            this.menuClick = false;
100
+        });
101
+    }
102
+
103
+    onMenuButtonClick(event) {
104
+        this.menuActive = !this.menuActive;
105
+        this.topbarMenuActive = false;
106
+        this.topbarRightClick = true;
107
+        this.menuClick = true;
108
+
109
+        if (this.isDesktop()) {
110
+            this.staticMenuDesktopInactive = !this.staticMenuDesktopInactive;
111
+        } else {
112
+            this.mobileMenuActive = !this.mobileMenuActive;
113
+            if (this.mobileMenuActive) {
114
+                this.blockBodyScroll();
115
+            } else {
116
+                this.unblockBodyScroll();
117
+            }
118
+        }
119
+
120
+        event.preventDefault();
121
+    }
122
+
123
+    onTopbarMobileButtonClick(event) {
124
+        this.mobileTopbarActive = !this.mobileTopbarActive;
125
+        event.preventDefault();
126
+    }
127
+
128
+    onRightMenuButtonClick(event) {
129
+        this.rightMenuActive = !this.rightMenuActive;
130
+        event.preventDefault();
131
+    }
132
+
133
+    onMenuClick($event) {
134
+        this.menuClick = true;
135
+
136
+        if (this.inlineMenuActive[this.currentInlineMenuKey] && !this.inlineMenuClick) {
137
+            this.inlineMenuActive[this.currentInlineMenuKey] = false;
138
+        }
139
+    }
140
+
141
+    onSearchKeydown(event) {
142
+        if (event.keyCode === 27) {
143
+            this.search = false;
144
+        }
145
+    }
146
+
147
+    onInlineMenuClick(event, key) {
148
+        if (key !== this.currentInlineMenuKey) {
149
+            this.inlineMenuActive[this.currentInlineMenuKey] = false;
150
+        }
151
+
152
+        this.inlineMenuActive[key] = !this.inlineMenuActive[key];
153
+        this.currentInlineMenuKey = key;
154
+        this.inlineMenuClick = true;
155
+    }
156
+
157
+    onTopbarItemClick(event, item) {
158
+        this.topbarItemClick = true;
159
+
160
+        if (this.activeTopbarItem === item) {
161
+            this.activeTopbarItem = null;
162
+        }
163
+        else {
164
+            this.activeTopbarItem = item;
165
+        }
166
+
167
+        if (item === 'search') {
168
+            this.search = !this.search;
169
+            this.searchClick = !this.searchClick;
170
+        }
171
+
172
+        event.preventDefault();
173
+    }
174
+
175
+    onTopbarSubItemClick(event) {
176
+        event.preventDefault();
177
+    }
178
+
179
+    onRTLChange(event) {
180
+        this.app.isRTL = event.checked;
181
+    }
182
+
183
+    onRippleChange(event) {
184
+        this.app.ripple = event.checked;
185
+        this.primengConfig.ripple = event.checked;
186
+    }
187
+
188
+    onConfigClick(event) {
189
+        this.configClick = true;
190
+    }
191
+
192
+    isDesktop() {
193
+        return window.innerWidth > 991;
194
+    }
195
+
196
+    isMobile() {
197
+        return window.innerWidth <= 991;
198
+    }
199
+
200
+    isOverlay() {
201
+        return this.app.menuMode === 'overlay';
202
+    }
203
+
204
+    isStatic() {
205
+        return this.app.menuMode === 'static';
206
+    }
207
+
208
+    isHorizontal() {
209
+        return this.app.menuMode === 'horizontal';
210
+    }
211
+
212
+    isSlim() {
213
+        return this.app.menuMode === 'slim';
214
+    }
215
+
216
+    blockBodyScroll(): void {
217
+        if (document.body.classList) {
218
+            document.body.classList.add('blocked-scroll');
219
+        } else {
220
+            document.body.className += ' blocked-scroll';
221
+        }
222
+    }
223
+
224
+    unblockBodyScroll(): void {
225
+        if (document.body.classList) {
226
+            document.body.classList.remove('blocked-scroll');
227
+        } else {
228
+            document.body.className = document.body.className.replace(new RegExp('(^|\\b)' +
229
+                'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
230
+        }
231
+    }
232
+
233
+    ngOnDestroy() {
234
+        if (this.documentClickListener) {
235
+            this.documentClickListener();
236
+        }
237
+    }
238
+}

+ 28
- 0
src/app/app.menu.component.ts Visa fil

@@ -0,0 +1,28 @@
1
+import {Component, OnInit} from '@angular/core';
2
+import {AppComponent} from './app.component';
3
+
4
+@Component({
5
+    selector: 'app-menu',
6
+    template: `
7
+        <ul class="layout-menu">
8
+            <li app-menuitem *ngFor="let item of model; let i = index;" [item]="item" [index]="i" [root]="true"></li>
9
+        </ul>
10
+    `
11
+})
12
+export class AppMenuComponent implements OnInit {
13
+
14
+    model: any[];
15
+
16
+    constructor(public app: AppComponent) {}
17
+
18
+    ngOnInit() {
19
+        this.model = [
20
+            {
21
+                label: 'Natan', icon: 'pi pi-fw pi-home',
22
+                items: [
23
+                    {label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/']},
24
+                ]
25
+            }
26
+        ];
27
+    }
28
+}

+ 20
- 0
src/app/app.menu.service.ts Visa fil

@@ -0,0 +1,20 @@
1
+import { Injectable } from '@angular/core';
2
+import { Subject } from 'rxjs';
3
+
4
+@Injectable()
5
+export class MenuService {
6
+
7
+    private menuSource = new Subject<string>();
8
+    private resetSource = new Subject();
9
+
10
+    menuSource$ = this.menuSource.asObservable();
11
+    resetSource$ = this.resetSource.asObservable();
12
+
13
+    onMenuStateChange(key: string) {
14
+        this.menuSource.next(key);
15
+    }
16
+
17
+    reset() {
18
+        this.resetSource.next();
19
+    }
20
+}

+ 208
- 0
src/app/app.menuitem.component.ts Visa fil

@@ -0,0 +1,208 @@
1
+import {ChangeDetectorRef, Component, Input, OnDestroy, OnInit} from '@angular/core';
2
+import {NavigationEnd, Router} from '@angular/router';
3
+import {animate, state, style, transition, trigger} from '@angular/animations';
4
+import {Subscription} from 'rxjs';
5
+import {filter} from 'rxjs/operators';
6
+import {MenuService} from './app.menu.service';
7
+import {AppMainComponent} from './app.main.component';
8
+
9
+@Component({
10
+    /* tslint:disable:component-selector */
11
+    selector: '[app-menuitem]',
12
+    /* tslint:enable:component-selector */
13
+    template: `
14
+        <ng-container>
15
+            <div *ngIf="root && item.visible !== false">
16
+                <span class="layout-menuitem-text">{{item.label}}</span>
17
+            </div>
18
+            <a [attr.href]="item.url" (click)="itemClick($event)" *ngIf="(!item.routerLink || item.items) && item.visible !== false" (keydown.enter)="itemClick($event)"
19
+               [attr.target]="item.target" [attr.tabindex]="0" [ngClass]="item.class" (mouseenter)="onMouseEnter()" pRipple
20
+               [pTooltip]="item.label" [tooltipDisabled]="active || !(root && app.isSlim() && !app.isMobile())">
21
+                <i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
22
+                <span class="layout-menuitem-text">{{item.label}}</span>
23
+                <span class="p-badge p-component p-badge-no-gutter" [ngClass]="item.badgeClass" *ngIf="item.badge && !root">{{item.badge}}</span>
24
+                <i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
25
+            </a>
26
+            <a (click)="itemClick($event)" *ngIf="(item.routerLink && !item.items) && item.visible !== false"
27
+               [routerLink]="item.routerLink" routerLinkActive="active-menuitem-routerlink" [routerLinkActiveOptions]="{exact: true}"
28
+               [attr.target]="item.target" [attr.tabindex]="0" [ngClass]="item.class" (mouseenter)="onMouseEnter()" pRipple
29
+               [pTooltip]="item.label" [tooltipDisabled]="active || !(root && app.isSlim() && !app.isMobile())">
30
+                <i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
31
+                <span class="layout-menuitem-text">{{item.label}}</span>
32
+                <span class="p-badge p-component p-badge-no-gutter" [ngClass]="item.badgeClass" *ngIf="item.badge && !root">{{item.badge}}</span>
33
+                <i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
34
+            </a>
35
+            <ul *ngIf="((item.items && root) || (item.items && active)) && item.visible !== false" [@children]="root ? 'visible' : active ? 'visibleAnimated' : 'hiddenAnimated'">
36
+                <ng-template ngFor let-child let-i="index" [ngForOf]="item.items">
37
+                    <li app-menuitem [item]="child" [index]="i" [parentKey]="key" [class]="child.badgeClass"></li>
38
+                </ng-template>
39
+            </ul>
40
+        </ng-container>
41
+    `,
42
+    host: {
43
+        '[class.layout-root-menuitem]': 'root || active',
44
+        '[class.active-menuitem]': '(active)'
45
+    },
46
+    animations: [
47
+        trigger('children', [
48
+            state('void', style({
49
+                height: '0px',
50
+                padding: '0px'
51
+            })),
52
+            state('hiddenAnimated', style({
53
+                height: '0px',
54
+                padding: '0px'
55
+            })),
56
+            state('visibleAnimated', style({
57
+                height: '*'
58
+            })),
59
+            state('visible', style({
60
+                height: '*'
61
+            })),
62
+            state('hidden', style({
63
+                height: '0px',
64
+                padding: '0px'
65
+            })),
66
+            transition('visibleAnimated => hiddenAnimated', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')),
67
+            transition('hiddenAnimated => visibleAnimated', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')),
68
+            transition('void => visibleAnimated, visibleAnimated => void',
69
+                animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
70
+        ])
71
+    ]
72
+})
73
+export class AppMenuitemComponent implements OnInit, OnDestroy {
74
+
75
+    @Input() item: any;
76
+
77
+    @Input() index: number;
78
+
79
+    @Input() root: boolean;
80
+
81
+    @Input() parentKey: string;
82
+
83
+    active = false;
84
+
85
+    menuSourceSubscription: Subscription;
86
+
87
+    menuResetSubscription: Subscription;
88
+
89
+    key: string;
90
+
91
+    constructor(public app: AppMainComponent, public router: Router, private cd: ChangeDetectorRef, private menuService: MenuService) {
92
+        this.menuSourceSubscription = this.menuService.menuSource$.subscribe(key => {
93
+            // deactivate current active menu
94
+            if (this.active && this.key !== key && key.indexOf(this.key) !== 0) {
95
+                this.active = false;
96
+            }
97
+        });
98
+
99
+        this.menuResetSubscription = this.menuService.resetSource$.subscribe(() => {
100
+            this.active = false;
101
+        });
102
+
103
+        this.router.events.pipe(filter(event => event instanceof NavigationEnd))
104
+            .subscribe(params => {
105
+                if (this.app.isHorizontal() || this.app.isSlim()) {
106
+                    this.active = false;
107
+                } else {
108
+                    if (this.item.routerLink) {
109
+                        this.updateActiveStateFromRoute();
110
+                    } else {
111
+                        this.active = false;
112
+                    }
113
+                }
114
+            });
115
+    }
116
+
117
+    ngOnInit() {
118
+        if (!(this.app.isHorizontal() || this.app.isSlim()) && this.item.routerLink) {
119
+            this.updateActiveStateFromRoute();
120
+        }
121
+
122
+        this.key = this.parentKey ? this.parentKey + '-' + this.index : String(this.index);
123
+    }
124
+
125
+    updateActiveStateFromRoute() {
126
+        this.active = this.router.isActive(this.item.routerLink[0], this.item.items ? false : true);
127
+    }
128
+
129
+    itemClick(event: Event) {
130
+        // avoid processing disabled items
131
+        if (this.item.disabled) {
132
+            event.preventDefault();
133
+            return;
134
+        }
135
+
136
+        // navigate with hover in horizontal mode
137
+        if (this.root) {
138
+            this.app.menuHoverActive = !this.app.menuHoverActive;
139
+        }
140
+
141
+        // notify other items
142
+        this.menuService.onMenuStateChange(this.key);
143
+
144
+        // execute command
145
+        if (this.item.command) {
146
+            this.item.command({originalEvent: event, item: this.item});
147
+        }
148
+
149
+        // toggle active state
150
+        if (this.item.items) {
151
+            this.active = !this.active;
152
+        } else {
153
+            // activate item
154
+            this.active = true;
155
+
156
+            // reset horizontal and slim menu
157
+            if (this.app.isHorizontal() || this.app.isSlim()) {
158
+                this.menuService.reset();
159
+                this.app.menuHoverActive = false;
160
+            }
161
+
162
+            if (!this.app.isStatic()) {
163
+                this.app.menuActive = false;
164
+            }
165
+
166
+            this.app.mobileMenuActive = false;
167
+        }
168
+
169
+        this.removeActiveInk(event);
170
+    }
171
+
172
+    onMouseEnter() {
173
+        // activate item on hover
174
+        if (this.root  && (this.app.isHorizontal() || this.app.isSlim()) && this.app.isDesktop()) {
175
+            if (this.app.menuHoverActive) {
176
+                this.menuService.onMenuStateChange(this.key);
177
+                this.active = true;
178
+            }
179
+        }
180
+    }
181
+
182
+    removeActiveInk(event: Event) {
183
+        const currentTarget = (event.currentTarget as HTMLElement);
184
+        setTimeout(() => {
185
+            if (currentTarget) {
186
+                const activeInk = currentTarget.querySelector('.p-ink-active');
187
+                if (activeInk) {
188
+                    if (activeInk.classList) {
189
+                        activeInk.classList.remove('p-ink-active');
190
+                    }
191
+                    else {
192
+                        activeInk.className = activeInk.className.replace(new RegExp('(^|\\b)' + 'p-ink-active'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
193
+                    }
194
+                }
195
+            }
196
+        }, 401);
197
+    }
198
+
199
+    ngOnDestroy() {
200
+        if (this.menuSourceSubscription) {
201
+            this.menuSourceSubscription.unsubscribe();
202
+        }
203
+
204
+        if (this.menuResetSubscription) {
205
+            this.menuResetSubscription.unsubscribe();
206
+        }
207
+    }
208
+}

+ 223
- 0
src/app/app.module.ts Visa fil

@@ -0,0 +1,223 @@
1
+import {NgModule} from '@angular/core';
2
+import {FormsModule} from '@angular/forms';
3
+import {HttpClientModule} from '@angular/common/http';
4
+import {BrowserModule} from '@angular/platform-browser';
5
+import {HashLocationStrategy, LocationStrategy} from '@angular/common';
6
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
7
+import {AppRoutingModule} from './app-routing.module';
8
+
9
+import {AccordionModule} from 'primeng/accordion';
10
+import {AutoCompleteModule} from 'primeng/autocomplete';
11
+import {AvatarModule} from 'primeng/avatar';
12
+import {AvatarGroupModule} from 'primeng/avatargroup';
13
+import {BadgeModule} from 'primeng/badge';
14
+import {BreadcrumbModule} from 'primeng/breadcrumb';
15
+import {ButtonModule} from 'primeng/button';
16
+import {CalendarModule} from 'primeng/calendar';
17
+import {CardModule} from 'primeng/card';
18
+import {CarouselModule} from 'primeng/carousel';
19
+import {CascadeSelectModule} from 'primeng/cascadeselect';
20
+import {ChartModule} from 'primeng/chart';
21
+import {CheckboxModule} from 'primeng/checkbox';
22
+import {ChipModule} from 'primeng/chip';
23
+import {ChipsModule} from 'primeng/chips';
24
+import {CodeHighlighterModule} from 'primeng/codehighlighter';
25
+import {ConfirmDialogModule} from 'primeng/confirmdialog';
26
+import {ConfirmPopupModule} from 'primeng/confirmpopup';
27
+import {ColorPickerModule} from 'primeng/colorpicker';
28
+import {ContextMenuModule} from 'primeng/contextmenu';
29
+import {DataViewModule} from 'primeng/dataview';
30
+import {DialogModule} from 'primeng/dialog';
31
+import {DividerModule} from 'primeng/divider';
32
+import {DropdownModule} from 'primeng/dropdown';
33
+import {FieldsetModule} from 'primeng/fieldset';
34
+import {FileUploadModule} from 'primeng/fileupload';
35
+import {FullCalendarModule} from '@fullcalendar/angular';
36
+import {GalleriaModule} from 'primeng/galleria';
37
+import {ImageModule} from 'primeng/image';
38
+import {InplaceModule} from 'primeng/inplace';
39
+import {InputNumberModule} from 'primeng/inputnumber';
40
+import {InputMaskModule} from 'primeng/inputmask';
41
+import {InputSwitchModule} from 'primeng/inputswitch';
42
+import {InputTextModule} from 'primeng/inputtext';
43
+import {InputTextareaModule} from 'primeng/inputtextarea';
44
+import {KnobModule} from 'primeng/knob';
45
+import {LightboxModule} from 'primeng/lightbox';
46
+import {ListboxModule} from 'primeng/listbox';
47
+import {MegaMenuModule} from 'primeng/megamenu';
48
+import {MenuModule} from 'primeng/menu';
49
+import {MenubarModule} from 'primeng/menubar';
50
+import {MessagesModule} from 'primeng/messages';
51
+import {MessageModule} from 'primeng/message';
52
+import {MultiSelectModule} from 'primeng/multiselect';
53
+import {OrderListModule} from 'primeng/orderlist';
54
+import {OrganizationChartModule} from 'primeng/organizationchart';
55
+import {OverlayPanelModule} from 'primeng/overlaypanel';
56
+import {PaginatorModule} from 'primeng/paginator';
57
+import {PanelModule} from 'primeng/panel';
58
+import {PanelMenuModule} from 'primeng/panelmenu';
59
+import {PasswordModule} from 'primeng/password';
60
+import {PickListModule} from 'primeng/picklist';
61
+import {ProgressBarModule} from 'primeng/progressbar';
62
+import {RadioButtonModule} from 'primeng/radiobutton';
63
+import {RatingModule} from 'primeng/rating';
64
+import {RippleModule} from 'primeng/ripple';
65
+import {ScrollPanelModule} from 'primeng/scrollpanel';
66
+import {ScrollTopModule} from 'primeng/scrolltop';
67
+import {SelectButtonModule} from 'primeng/selectbutton';
68
+import {SidebarModule} from 'primeng/sidebar';
69
+import {SkeletonModule} from 'primeng/skeleton';
70
+import {SlideMenuModule} from 'primeng/slidemenu';
71
+import {SliderModule} from 'primeng/slider';
72
+import {SplitButtonModule} from 'primeng/splitbutton';
73
+import {SplitterModule} from 'primeng/splitter';
74
+import {StepsModule} from 'primeng/steps';
75
+import {TabMenuModule} from 'primeng/tabmenu';
76
+import {TableModule} from 'primeng/table';
77
+import {TabViewModule} from 'primeng/tabview';
78
+import {TagModule} from 'primeng/tag';
79
+import {TerminalModule} from 'primeng/terminal';
80
+import {TieredMenuModule} from 'primeng/tieredmenu';
81
+import {TimelineModule} from 'primeng/timeline';
82
+import {ToastModule} from 'primeng/toast';
83
+import {ToggleButtonModule} from 'primeng/togglebutton';
84
+import {ToolbarModule} from 'primeng/toolbar';
85
+import {TooltipModule} from 'primeng/tooltip';
86
+import {TreeModule} from 'primeng/tree';
87
+import {TreeTableModule} from 'primeng/treetable';
88
+import {VirtualScrollerModule} from 'primeng/virtualscroller';
89
+
90
+import {AppCodeModule} from './app.code.component';
91
+import {AppComponent} from './app.component';
92
+import {AppMainComponent} from './app.main.component';
93
+import {AppConfigComponent} from './app.config.component';
94
+import {AppMenuComponent} from './app.menu.component';
95
+import {AppMenuitemComponent} from './app.menuitem.component';
96
+import {AppInlineMenuComponent} from './app.inlinemenu.component';
97
+import {AppRightMenuComponent} from './app.rightmenu.component';
98
+import {AppBreadcrumbComponent} from './app.breadcrumb.component';
99
+import {AppTopBarComponent} from './app.topbar.component';
100
+import {AppFooterComponent} from './app.footer.component';
101
+
102
+import {MenuService} from './app.menu.service';
103
+import {AppBreadcrumbService} from './app.breadcrumb.service';
104
+
105
+import dayGridPlugin from '@fullcalendar/daygrid';
106
+import timeGridPlugin from '@fullcalendar/timegrid';
107
+import interactionPlugin from '@fullcalendar/interaction';
108
+
109
+FullCalendarModule.registerPlugins([
110
+    dayGridPlugin,
111
+    timeGridPlugin,
112
+    interactionPlugin
113
+]);
114
+
115
+@NgModule({
116
+    imports: [
117
+        BrowserModule,
118
+        FormsModule,
119
+        AppRoutingModule,
120
+        HttpClientModule,
121
+        BrowserAnimationsModule,
122
+        AccordionModule,
123
+        AutoCompleteModule,
124
+        AvatarModule,
125
+        AvatarGroupModule,
126
+        BadgeModule,
127
+        BreadcrumbModule,
128
+        ButtonModule,
129
+        CalendarModule,
130
+        CardModule,
131
+        CarouselModule,
132
+        CascadeSelectModule,
133
+        ChartModule,
134
+        CheckboxModule,
135
+        ChipModule,
136
+        ChipsModule,
137
+        CodeHighlighterModule,
138
+        ConfirmDialogModule,
139
+        ConfirmPopupModule,
140
+        ColorPickerModule,
141
+        ContextMenuModule,
142
+        DataViewModule,
143
+        DialogModule,
144
+        DividerModule,
145
+        DropdownModule,
146
+        FieldsetModule,
147
+        FileUploadModule,
148
+        FullCalendarModule,
149
+        GalleriaModule,
150
+        ImageModule,
151
+        InplaceModule,
152
+        InputNumberModule,
153
+        InputMaskModule,
154
+        InputSwitchModule,
155
+        InputTextModule,
156
+        InputTextareaModule,
157
+        KnobModule,
158
+        LightboxModule,
159
+        ListboxModule,
160
+        MegaMenuModule,
161
+        MenuModule,
162
+        MenubarModule,
163
+        MessageModule,
164
+        MessagesModule,
165
+        MultiSelectModule,
166
+        OrderListModule,
167
+        OrganizationChartModule,
168
+        OverlayPanelModule,
169
+        PaginatorModule,
170
+        PanelModule,
171
+        PanelMenuModule,
172
+        PasswordModule,
173
+        PickListModule,
174
+        ProgressBarModule,
175
+        RadioButtonModule,
176
+        RatingModule,
177
+        RippleModule,
178
+        ScrollPanelModule,
179
+        ScrollTopModule,
180
+        SelectButtonModule,
181
+        SidebarModule,
182
+        SkeletonModule,
183
+        SlideMenuModule,
184
+        SliderModule,
185
+        SplitButtonModule,
186
+        SplitterModule,
187
+        StepsModule,
188
+        TableModule,
189
+        TabMenuModule,
190
+        TabViewModule,
191
+        TagModule,
192
+        TerminalModule,
193
+        TimelineModule,
194
+        TieredMenuModule,
195
+        ToastModule,
196
+        ToggleButtonModule,
197
+        ToolbarModule,
198
+        TooltipModule,
199
+        TreeModule,
200
+        TreeTableModule,
201
+        VirtualScrollerModule,
202
+        AppCodeModule
203
+    ],
204
+    declarations: [
205
+        AppComponent,
206
+        AppMainComponent,
207
+        AppConfigComponent,
208
+        AppMenuComponent,
209
+        AppMenuitemComponent,
210
+        AppInlineMenuComponent,
211
+        AppRightMenuComponent,
212
+        AppBreadcrumbComponent,
213
+        AppTopBarComponent,
214
+        AppFooterComponent
215
+    ],
216
+    providers: [
217
+        {provide: LocationStrategy, useClass: HashLocationStrategy},
218
+        MenuService, AppBreadcrumbService
219
+    ],
220
+    bootstrap: [AppComponent]
221
+})
222
+export class AppModule {
223
+}

+ 70
- 0
src/app/app.rightmenu.component.html Visa fil

@@ -0,0 +1,70 @@
1
+<p-sidebar [(visible)]="appMain.rightMenuActive" [position]="app.isRTL ? 'left' : 'right'" [blockScroll]="true" [showCloseIcon]="false" [baseZIndex]="1000" [styleClass]="'layout-rightmenu p-sidebar-sm fs-small py-3 ' + (app.isRTL ? 'pl-0 pr-3' : 'pl-3 pr-0')">
2
+    <div class="online-members flex flex-column mt-3" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}">
3
+        <h6 class="header">ONLINE MEMBERS</h6>
4
+        <div class="flex flex-row flex-wrap">
5
+            <img class="m-1" src="assets/demo/images/avatar/avatar-1.png" alt="avatar-1"/>
6
+            <img class="m-1" src="assets/demo/images/avatar/avatar-2.png" alt="avatar-2"/>
7
+            <img class="m-1" src="assets/demo/images/avatar/avatar-3.png" alt="avatar-3"/>
8
+            <img class="m-1" src="assets/demo/images/avatar/avatar-4.png" alt="avatar-4"/>
9
+            <img class="m-1" src="assets/demo/images/avatar/avatar-5.png" alt="avatar-5"/>
10
+            <img class="m-1" src="assets/demo/images/avatar/avatar-6.png" alt="avatar-6"/>
11
+            <img class="m-1" src="assets/demo/images/avatar/avatar-7.png" alt="avatar-7"/>
12
+            <img class="m-1" src="assets/demo/images/avatar/avatar-8.png" alt="avatar-8"/>
13
+            <img class="m-1" src="assets/demo/images/avatar/avatar-9.png" alt="avatar-9"/>
14
+            <img class="m-1" src="assets/demo/images/avatar/avatar-10.png" alt="avatar-10"/>
15
+            <img class="m-1" src="assets/demo/images/avatar/avatar-11.png" alt="avatar-11"/>
16
+            <img class="m-1" src="assets/demo/images/avatar/avatar-12.png" alt="avatar-12"/>
17
+            <img class="m-1" src="assets/demo/images/avatar/avatar-13.png" alt="avatar-13"/>
18
+            <img class="m-1" src="assets/demo/images/avatar/avatar-14.png" alt="avatar-14"/>
19
+            <img class="m-1" src="assets/demo/images/avatar/avatar-15.png" alt="avatar-15"/>
20
+            <img class="m-1" src="assets/demo/images/avatar/avatar-16.png" alt="avatar-16"/>
21
+        </div>
22
+        <span class="mt-3"><b>+19</b> Costumers</span>
23
+    </div>
24
+    <div class="latest-activity flex flex-column mt-6" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}">
25
+        <h6 class="header">LATEST ACTIVITY</h6>
26
+        <div class="flex flex-row pt-2">
27
+            <i class="pi pi-images align-self-start p-2" [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}"></i>
28
+            <div class="flex flex-column">
29
+                <span class="font-bold mb-1">New Sale</span>
30
+                <span class="mb-2">Richard Jones has purchased a blue t-shirt for $79.</span>
31
+                <span class="flex align-items-center">
32
+                    <img [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}" src="assets/demo/images/avatar/activity-1.png" alt=""/>
33
+                    <small class="muted-text">Emmy Adams, 21.40</small>
34
+                </span>
35
+            </div>
36
+        </div>
37
+        <div class="flex flex-row pt-3">
38
+            <i class="pi pi-images align-self-start p-2" [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}"></i>
39
+            <div class="flex flex-column">
40
+                <span class="font-bold mb-1">Withdrawal Initiated</span>
41
+                <span class="mb-2">Your request for withdrawal of $2500 has been initiated.</span>
42
+                <span class="flex align-items-center">
43
+                    <img [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}" src="assets/demo/images/avatar/activity-2.png" alt="avatar-2"/>
44
+                    <small class="muted-text">Emily Walter, 21.40</small>
45
+                </span>
46
+            </div>
47
+        </div>
48
+        <div class="flex flex-row pt-3">
49
+            <i class="pi pi-images align-self-start p-2" [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}"></i>
50
+            <div class="flex flex-column">
51
+                <span class="font-bold mb-1">Question Received</span>
52
+                <span class="mb-2">Jane Davis has posted a new question about your product.</span>
53
+                <span class="flex align-items-center">
54
+                    <img [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}" src="assets/demo/images/avatar/activity-3.png" alt="avatar-3"/>
55
+                    <small class="muted-text">Jane Davis, 21.45</small>
56
+                </span>
57
+            </div>
58
+        </div>
59
+    </div>
60
+    <div class="next-events flex flex-column mt-6" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}">
61
+        <h6 class="header">NEXT EVENTS</h6>
62
+        <ul>
63
+            <li><i class="pi pi-eye" [ngClass]="{'mr-3': !app.isRTL, 'ml-3': app.isRTL}"></i>A/B Test</li>
64
+            <li><i class="pi pi-video" [ngClass]="{'mr-3': !app.isRTL, 'ml-3': app.isRTL}"></i>Video Shoot</li>
65
+            <li><i class="pi pi-sitemap" [ngClass]="{'mr-3': !app.isRTL, 'ml-3': app.isRTL}"></i>Board Meeting</li>
66
+            <li><i class="pi pi-compass" [ngClass]="{'mr-3': !app.isRTL, 'ml-3': app.isRTL}"></i>Q4 Planning</li>
67
+            <li><i class="pi pi-palette" [ngClass]="{'mr-3': !app.isRTL, 'ml-3': app.isRTL}"></i>Design Training</li>
68
+        </ul>
69
+    </div>
70
+</p-sidebar>

+ 11
- 0
src/app/app.rightmenu.component.ts Visa fil

@@ -0,0 +1,11 @@
1
+import {Component} from '@angular/core';
2
+import { AppComponent } from './app.component';
3
+import {AppMainComponent} from './app.main.component';
4
+
5
+@Component({
6
+    selector: 'app-rightmenu',
7
+    templateUrl: './app.rightmenu.component.html'
8
+})
9
+export class AppRightMenuComponent {
10
+    constructor(public appMain: AppMainComponent, public app: AppComponent) {}
11
+}

+ 166
- 0
src/app/app.topbar.component.html Visa fil

@@ -0,0 +1,166 @@
1
+<div class="layout-topbar shadow-4">
2
+    <div class="layout-topbar-left">
3
+        <a class="layout-topbar-logo" routerLink="/">
4
+            <img id="app-logo" src="assets/layout/images/logo-light.png" style="height: 2.25rem">
5
+            <h3 class="m-1"> NATAN</h3>
6
+        </a>
7
+
8
+        <a class="layout-menu-button shadow-6" (click)="appMain.onMenuButtonClick($event)" pRipple>
9
+            <i class="pi pi-chevron-right"></i>
10
+        </a>
11
+
12
+        <a class="layout-topbar-mobile-button" (click)="appMain.onTopbarMobileButtonClick($event)" pRipple>
13
+            <i class="pi pi-ellipsis-v fs-large"></i>
14
+        </a>
15
+    </div>
16
+
17
+    <div class="layout-topbar-right" [ngClass]="{'layout-topbar-mobile-active': appMain.mobileTopbarActive}">
18
+        <div class="layout-topbar-actions-left">
19
+            <!-- <p-megaMenu [model]="model" styleClass="layout-megamenu"></p-megaMenu> -->
20
+        </div>
21
+        <div class="layout-topbar-actions-right">
22
+            <ul class="layout-topbar-items">
23
+                <!-- <li class="layout-topbar-item layout-search-item">
24
+                    <a class="layout-topbar-action rounded-circle" (click)="appMain.onTopbarItemClick($event, 'search')" pRipple>
25
+                        <i class="pi pi-search fs-large"></i>
26
+                    </a>
27
+
28
+                    <div class="layout-search-panel p-inputgroup" [@topbarActionPanelAnimation]="'visible'" *ngIf="appMain.search" (@topbarActionPanelAnimation.done)="onSearchAnimationEnd($event)">
29
+                        <span class="p-inputgroup-addon"><i class="pi pi-search"></i></span>
30
+                        <input #searchInput type="text" pInputText placeholder="Search" (click)="appMain.searchClick = true;" (keydown)="appMain.onSearchKeydown($event)">
31
+                        <span class="p-inputgroup-addon">
32
+                            <button pButton pRipple type="button" icon="pi pi-times" class="p-button-rounded p-button-text p-button-plain" (click)="appMain.searchClick = false;"></button>
33
+                        </span>
34
+                    </div>
35
+                </li>
36
+                <li class="layout-topbar-item notifications">
37
+                    <a class="layout-topbar-action rounded-circle" (click)="appMain.onTopbarItemClick($event, 'notifications')" pRipple>
38
+                        <span class="p-overlay-badge">
39
+                            <i class="pi pi-bell fs-large"></i>
40
+                            <span class="p-badge p-badge-warning p-badge-dot"></span>
41
+                        </span>
42
+                    </a>
43
+
44
+                    <ul class="layout-topbar-action-panel shadow-6" [@topbarActionPanelAnimation]="'visible'" *ngIf="appMain.activeTopbarItem === 'notifications'">
45
+                        <li class="mb-3">
46
+                            <span class="px-3 fs-small">You have <b>4</b> new notifications</span>
47
+                        </li>
48
+                        <li class="layout-topbar-action-item">
49
+                            <div class="flex flex-row align-items-center">
50
+                                <img src="assets/demo/images/avatar/avatar-1.png"/>
51
+                                <div class="flex flex-column" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}" style="flex-grow: 1;">
52
+                                    <div class="flex align-items-center justify-content-between mb-1">
53
+                                        <span class="fs-small font-bold">Jerome Bell</span>
54
+                                        <small>42 mins ago</small>
55
+                                    </div>
56
+                                    <span class="fs-small">How to write content about your photographs?</span>
57
+                                </div>
58
+                            </div>
59
+                        </li>
60
+                        <li class="layout-topbar-action-item">
61
+                            <div class="flex flex-row align-items-center">
62
+                                <img src="assets/demo/images/avatar/avatar-2.png"/>
63
+                                <div class="flex flex-column" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}" style="flex-grow: 1;">
64
+                                    <div class="flex align-items-center justify-content-between mb-1">
65
+                                        <span class="fs-small font-bold">Cameron Williamson</span>
66
+                                        <small>48 mins ago</small>
67
+                                    </div>
68
+                                    <span class="fs-small">Start a blog to reach your creative peak.</span>
69
+                                </div>
70
+                            </div>
71
+                        </li>
72
+                        <li class="layout-topbar-action-item">
73
+                            <div class="flex flex-row align-items-center">
74
+                                <img src="assets/demo/images/avatar/avatar-3.png"/>
75
+                                <div class="flex flex-column" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}" style="flex-grow: 1;">
76
+                                    <div class="flex align-items-center justify-content-between mb-1">
77
+                                        <span class="fs-small font-bold">Anna Miles</span>
78
+                                        <small>1 day ago</small>
79
+                                    </div>
80
+                                    <span class="fs-small">Caring is the new marketing</span>
81
+                                </div>
82
+                            </div>
83
+                        </li>
84
+                        <li class="layout-topbar-action-item">
85
+                            <div class="flex flex-row align-items-center">
86
+                                <img src="assets/demo/images/avatar/avatar-4.png"/>
87
+                                <div class="flex flex-column" [ngClass]="{'ml-3': !app.isRTL, 'mr-3': app.isRTL}" style="flex-grow: 1;">
88
+                                    <div class="flex align-items-center justify-content-between mb-1">
89
+                                        <span class="fs-small font-bold">Arlene Mccoy</span>
90
+                                        <small>4 day ago</small>
91
+                                    </div>
92
+                                    <span class="fs-small">Starting your traveling blog with Vasco.</span>
93
+                                </div>
94
+                            </div>
95
+                        </li>
96
+                    </ul>
97
+                </li>
98
+                <li class="layout-topbar-item app">
99
+                    <a class="layout-topbar-action rounded-circle" (click)="appMain.onTopbarItemClick($event, 'apps')" pRipple>
100
+                        <i class="pi pi-table fs-large"></i>
101
+                    </a>
102
+
103
+                    <div class="layout-topbar-action-panel shadow-6" [@topbarActionPanelAnimation]="'visible'" *ngIf="appMain.activeTopbarItem === 'apps'">
104
+                        <div class="grid grid-nogutter">
105
+                            <div class="layout-topbar-action-item col-4">
106
+                                <a class="flex align-items-center flex-column text-color" pRipple>
107
+                                    <i class="pi pi-image action indigo-bgcolor white-color"></i>
108
+                                    <span>Products</span>
109
+                                </a>
110
+                            </div>
111
+                            <div class="layout-topbar-action-item col-4">
112
+                                <a class="flex align-items-center flex-column text-color" pRipple>
113
+                                    <i class="pi pi-file-pdf action orange-bgcolor white-color"></i>
114
+                                    <span>Reports</span>
115
+                                </a>
116
+                            </div>
117
+                            <div class="layout-topbar-action-item col-4">
118
+                                <a class="flex align-items-center flex-column text-color" pRipple>
119
+                                    <i class="pi pi-dollar action teal-bgcolor white-color"></i>
120
+                                    <span>Balance</span>
121
+                                </a>
122
+                            </div>
123
+                            <div class="layout-topbar-action-item col-4">
124
+                                <a class="flex align-items-center flex-column text-color" pRipple>
125
+                                    <i class="pi pi-cog action pink-bgcolor white-color"></i>
126
+                                    <span>Settings</span>
127
+                                </a>
128
+                            </div>
129
+                            <div class="layout-topbar-action-item col-4">
130
+                                <a class="flex align-items-center flex-column text-color" pRipple>
131
+                                    <i class="pi pi-key action bluegrey-bgcolor white-color"></i>
132
+                                    <span>Credentials</span>
133
+                                </a>
134
+                            </div>
135
+                            <div class="layout-topbar-action-item col-4">
136
+                                <a class="flex align-items-center justify-content-center flex-column text-color" pRipple>
137
+                                    <i class="pi pi-sitemap action cyan-bgcolor white-color"></i>
138
+                                    <span>Sitemap</span>
139
+                                </a>
140
+                            </div>
141
+                        </div>
142
+                    </div>
143
+                </li> -->
144
+                <li class="layout-topbar-item">
145
+                    <a class="layout-topbar-action flex flex-row justify-content-center align-items-center px-2 rounded-circle" (click)="appMain.onTopbarItemClick($event, 'profile')" pRipple>
146
+                        <img src="assets/demo/images/avatar/amyelsner.png" alt="avatar" style="width: 32px; height: 32px;">
147
+                    </a>
148
+
149
+                    <ul class="layout-topbar-action-panel shadow-6" [@topbarActionPanelAnimation]="'visible'" *ngIf="appMain.activeTopbarItem === 'profile'">
150
+                        <li class="layout-topbar-action-item">
151
+                            <a class="flex flex-row align-items-center" pRipple>
152
+                                <i class="pi pi-power-off" [ngClass]="{'mr-2': !app.isRTL, 'ml-2': app.isRTL}"></i>
153
+                                <span>Logout</span>
154
+                            </a>
155
+                        </li>
156
+                    </ul>
157
+                </li>
158
+                <!-- <li class="layout-topbar-item">
159
+                    <a class="layout-topbar-action rounded-circle" (click)="appMain.onRightMenuButtonClick($event)" pRipple>
160
+                        <i class="pi fs-large" [ngClass]="{'pi-arrow-left': !app.isRTL, 'pi-arrow-right': app.isRTL}"></i>
161
+                    </a>
162
+                </li> -->
163
+            </ul>
164
+        </div>
165
+    </div>
166
+</div>

+ 126
- 0
src/app/app.topbar.component.ts Visa fil

@@ -0,0 +1,126 @@
1
+import { Component, ElementRef, ViewChild } from '@angular/core';
2
+import { trigger, style, transition, animate, AnimationEvent } from '@angular/animations';
3
+import { MegaMenuItem } from 'primeng/api';
4
+import { AppComponent } from './app.component';
5
+import { AppMainComponent } from './app.main.component';
6
+@Component({
7
+    selector: 'app-topbar',
8
+    templateUrl: './app.topbar.component.html',
9
+    animations: [
10
+        trigger('topbarActionPanelAnimation', [
11
+            transition(':enter', [
12
+                style({opacity: 0, transform: 'scaleY(0.8)'}),
13
+                animate('.12s cubic-bezier(0, 0, 0.2, 1)', style({ opacity: 1, transform: '*' })),
14
+              ]),
15
+              transition(':leave', [
16
+                animate('.1s linear', style({ opacity: 0 }))
17
+              ])
18
+        ])
19
+    ]
20
+})
21
+export class AppTopBarComponent {
22
+
23
+    constructor(public appMain: AppMainComponent, public app: AppComponent) {
24
+    }
25
+
26
+    activeItem: number;
27
+
28
+    model: MegaMenuItem[] = [
29
+        {
30
+            label: 'UI KIT',
31
+            items: [
32
+                [
33
+                    {
34
+                        label: 'UI KIT 1',
35
+                        items: [
36
+                            { label: 'Form Layout', icon: 'pi pi-fw pi-id-card', routerLink: ['/uikit/formlayout'] },
37
+                            { label: 'Input', icon: 'pi pi-fw pi-check-square', routerLink: ['/uikit/input'] },
38
+                            { label: 'Float Label', icon: 'pi pi-fw pi-bookmark', routerLink: ['/uikit/floatlabel'] },
39
+                            { label: 'Button', icon: 'pi pi-fw pi-mobile', routerLink: ['/uikit/button'] },
40
+                            { label: 'File', icon: 'pi pi-fw pi-file', routerLink: ['/uikit/file'] }
41
+                        ]
42
+                    }
43
+                ],
44
+                [
45
+                    {
46
+                        label: 'UI KIT 2',
47
+                        items: [
48
+                            { label: 'Table', icon: 'pi pi-fw pi-table', routerLink: ['/uikit/table'] },
49
+                            { label: 'List', icon: 'pi pi-fw pi-list', routerLink: ['/uikit/list'] },
50
+                            { label: 'Tree', icon: 'pi pi-fw pi-share-alt', routerLink: ['/uikit/tree'] },
51
+                            { label: 'Panel', icon: 'pi pi-fw pi-tablet', routerLink: ['/uikit/panel'] },
52
+                            { label: 'Chart', icon: 'pi pi-fw pi-chart-bar', routerLink: ['/uikit/charts'] }
53
+                        ]
54
+                    }
55
+                ],
56
+                [
57
+                    {
58
+                        label: 'UI KIT 3',
59
+                        items: [
60
+                            { label: 'Overlay', icon: 'pi pi-fw pi-clone', routerLink: ['/uikit/overlay'] },
61
+                            { label: 'Media', icon: 'pi pi-fw pi-image', routerLink: ['/uikit/media'] },
62
+                            { label: 'Menu', icon: 'pi pi-fw pi-bars', routerLink: ['/uikit/menu'] },
63
+                            { label: 'Message', icon: 'pi pi-fw pi-comment', routerLink: ['/uikit/message'] },
64
+                            { label: 'Misc', icon: 'pi pi-fw pi-circle-off', routerLink: ['/uikit/misc'] }
65
+                        ]
66
+                    }
67
+                ]
68
+            ]
69
+        },
70
+        {
71
+            label: 'UTILITIES',
72
+            items: [
73
+                [
74
+                    {
75
+                        label: 'UTILITIES 1',
76
+                        items: [
77
+                            { label: 'Display', icon: 'pi pi-fw pi-desktop', routerLink: ['utilities/display'] },
78
+                            { label: 'Elevation', icon: 'pi pi-fw pi-external-link', routerLink: ['utilities/elevation'] }
79
+                        ]
80
+                    },
81
+                    {
82
+                        label: 'UTILITIES 2',
83
+                        items: [
84
+                            { label: 'FlexBox', icon: 'pi pi-fw pi-directions', routerLink: ['utilities/flexbox'] }
85
+                        ]
86
+                    }
87
+                ],
88
+                [
89
+                    {
90
+                        label: 'UTILITIES 3',
91
+                        items: [
92
+                            { label: 'Icons', icon: 'pi pi-fw pi-search', routerLink: ['utilities/icons'] }
93
+                        ]
94
+                    },
95
+                    {
96
+                        label: 'UTILITIES 4',
97
+                        items: [
98
+                            { label: 'Text', icon: 'pi pi-fw pi-pencil', routerLink: ['utilities/text'] },
99
+                            { label: 'Widgets', icon: 'pi pi-fw pi-star-o', routerLink: ['utilities/widgets'] }
100
+                        ]
101
+                    }
102
+                ],
103
+                [
104
+                    {
105
+                        label: 'UTILITIES 5',
106
+                        items: [
107
+                            { label: 'Grid System', icon: 'pi pi-fw pi-th-large', routerLink: ['utilities/grid'] },
108
+                            { label: 'Spacing', icon: 'pi pi-fw pi-arrow-right', routerLink: ['utilities/spacing'] },
109
+                            { label: 'Typography', icon: 'pi pi-fw pi-align-center', routerLink: ['utilities/typography'] }
110
+                        ]
111
+                    }
112
+                ],
113
+            ]
114
+        }
115
+    ];
116
+
117
+    @ViewChild('searchInput') searchInputViewChild: ElementRef;
118
+
119
+    onSearchAnimationEnd(event: AnimationEvent) {
120
+        switch(event.toState) {
121
+            case 'visible':
122
+                this.searchInputViewChild.nativeElement.focus();
123
+            break;
124
+        }
125
+    }
126
+}

+ 25
- 0
src/app/pages/dashboard/dashboard.module.ts Visa fil

@@ -0,0 +1,25 @@
1
+import { NgModule } from '@angular/core';
2
+import { CommonModule } from '@angular/common';
3
+import { DashboardComponent } from './dashboard/dashboard.component';
4
+import { RouterModule, Routes } from '@angular/router';
5
+import { TreeModule } from 'primeng/tree';
6
+
7
+export const routes: Routes = [
8
+  {
9
+      path: 'dashboard',
10
+      component: DashboardComponent,
11
+      data: {roles: ['']},
12
+  }
13
+];
14
+
15
+@NgModule({
16
+  declarations: [
17
+    DashboardComponent
18
+  ],
19
+  imports: [
20
+    CommonModule,
21
+    RouterModule.forChild(routes),
22
+    TreeModule
23
+  ]
24
+})
25
+export class DashboardModule { }

+ 79
- 0
src/app/pages/dashboard/dashboard/dashboard.component.html Visa fil

@@ -0,0 +1,79 @@
1
+<div class="grid">
2
+    <div class="col-12">
3
+        <div class="card docs">
4
+
5
+            <h5>Environnement</h5>
6
+            <p>Angular 12 et PrimeNG 12</p>
7
+            <p>Lien du template : <a
8
+                    href="https://www.primefaces.org/ultima-ng">https://www.primefaces.org/ultima-ng</a></p>
9
+            <p>Lien de la documentation <a
10
+                    href="https://primefaces.org/primeng/showcase/#/setup">https://primefaces.org/primeng/showcase/#/setup</a>
11
+            </p>
12
+            <p>Vous trouverer a la racine du projet le fichier .zip du template ultima. Vous pouvez vous appuyer dessus
13
+                pour la mise en page de vos components.</p>
14
+
15
+
16
+            <h5>Exercice</h5>
17
+            <p>L'objectif est de développer le module candidat.</p>
18
+            <h6>Liste des Components</h6>
19
+            <ul>
20
+                <li>Le component "CandidatListComponent" affichera la liste des candidats avec pagination. il sera
21
+                    possible de faire une recherche sur cette liste en incluant le component CandidateSearchComponent.
22
+                </li>
23
+                <li>Le component "CandidatSearchbarComponent" affichera un formulaire de recherche par prenom, nom,
24
+                    email. Ce component devra apparaitre sur la liste des candidats.</li>
25
+                <li>Le component "CandidatDetailComponent" affichera un formulaire de mise a jour du candidat.</li>
26
+                <li>Le component "CandidatSidebarComponent" affichera une fenetre sidebar qui permettra de creer un
27
+                    nouveau candidat ou mettre à jour rapidement le candidat selectionné.</li>
28
+            </ul>
29
+
30
+            <h6>Liste des services</h6>
31
+            <ul>
32
+                <li>Le service "candidate.service.ts" devra comporter les api de Search, getById et Delete</li>
33
+                <li>Le service "candidate-list.service.ts" sera utilisé dans le cadre du chargement des candidats. (Voir
34
+                    Recommandations)</li>
35
+            </ul>
36
+
37
+
38
+            <h5>Stories</h5>
39
+            <p>- Ajouter une nouvelle entrée "Candidats" au menu de gauche.</p>
40
+            <p>
41
+                En tant qu'utilisateur, je clique sur l'entrée "Candidats" du menu gauche principal.<br>
42
+                Une fois sur la liste des candidats, je peux faire une recherche en fonction du nom, prenom ou email du
43
+                candidat.<br>
44
+                La liste sera un tableau de 5 colonnes [Id, Prenom, Nom, Emails, Actions(edit,delete) ] avec une
45
+                pagination.
46
+                Sur cette liste ajouter un bouton "Add". En cliquant sur Add, j'affiche le component Sidebar qui permet de
47
+                créer un nouveau candidat.
48
+                Vous pouvez editer le candidat de deux facons :
49
+            </p>
50
+            <ul>
51
+                <li>Soit en cliquant sur le bouton edit en fin de chaque ligne. Cette action ouvrira l'écran de
52
+                    detail du candidat avec les données préchargées à mettre à jour./li>
53
+                <li>Soit en cliquant sur la ligne. Cela ouvrira l'ecran sidebar de modification d'un candidat.</li>
54
+            </ul>
55
+
56
+
57
+            <h5>Recommandations</h5>
58
+            <p>- Pour les formulaires, vous pouvez utliser soit les Template-Driven ou Reactive Forms</p>
59
+            <p>- Sur les components "candidate-list", "candidate-sidebar" et "candidate-searchbar", il faudra utiliser les "BehaviorSubject" et "Resolve".
60
+            <br>Voici quelque liens explicatifs:</p>
61
+            <ul>
62
+                <li><a href="https://bcodes.io/blog/post/route-resolvers-rxjs-behaviorsubject-with-combinelatest">Lien
63
+                        1</a></li>
64
+                <li><a
65
+                        href="https://www.istruction.nl/blog/2018/9/20/angular-observable-data-services-resolve-and-the-behaviorsubject">Lien
66
+                        2</a></li>
67
+            </ul>
68
+
69
+            <p>- Les fichiers de données seront stockés dans le repertoire: "assets/demo/data" au format JSON </p>
70
+
71
+            <div>
72
+                <h5>Organisation du projet</h5>
73
+                <p-tree [value]="files" layout="horizontal" selectionMode="single" [(selection)]="selectedFiles">
74
+                </p-tree>
75
+            </div>
76
+
77
+        </div>
78
+    </div>
79
+</div>

+ 0
- 0
src/app/pages/dashboard/dashboard/dashboard.component.scss Visa fil


+ 33
- 0
src/app/pages/dashboard/dashboard/dashboard.component.ts Visa fil

@@ -0,0 +1,33 @@
1
+import { Component, OnInit } from '@angular/core';
2
+import { TreeNode } from 'primeng/api';
3
+import { AppBreadcrumbService } from 'src/app/app.breadcrumb.service';
4
+import { NodeService } from 'src/app/shared/services/node.service';
5
+
6
+@Component({
7
+  selector: 'app-dashboard',
8
+  templateUrl: './dashboard.component.html',
9
+  styleUrls: ['./dashboard.component.scss']
10
+})
11
+export class DashboardComponent implements OnInit {
12
+
13
+  files: TreeNode[];
14
+  selectedFiles: TreeNode;
15
+
16
+  constructor(private breadcrumbService: AppBreadcrumbService, private nodeService: NodeService) {
17
+    this.breadcrumbService.setItems([
18
+      { label: 'Dashboard' }
19
+    ]);
20
+  }
21
+
22
+  ngOnInit(): void {
23
+    this.nodeService.getFiles().then(files => {
24
+      this.files = [{
25
+        label: 'src',
26
+        "expanded":true,
27
+        children: files
28
+      }];
29
+    });
30
+
31
+  }
32
+
33
+}

+ 12
- 0
src/app/pages/pages.module.ts Visa fil

@@ -0,0 +1,12 @@
1
+import { NgModule } from '@angular/core';
2
+import { PagesRoutingModule } from './pages.routing.module';
3
+
4
+@NgModule({
5
+    declarations: [],
6
+    imports: [
7
+        PagesRoutingModule,
8
+    ],
9
+    providers: []
10
+})
11
+export class PagesModule {
12
+}

+ 19
- 0
src/app/pages/pages.routing.module.ts Visa fil

@@ -0,0 +1,19 @@
1
+import {NgModule} from '@angular/core';
2
+import {RouterModule, Routes} from '@angular/router';
3
+
4
+export const pagesRouteList: Routes = [
5
+    {
6
+        path: 'dashboard',
7
+        loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule)
8
+    }
9
+    
10
+];
11
+
12
+@NgModule({
13
+    declarations: [],
14
+    imports: [
15
+        RouterModule.forChild(pagesRouteList)
16
+    ]
17
+})
18
+export class PagesRoutingModule {
19
+}

+ 7
- 0
src/app/shared/models/candidate.ts Visa fil

@@ -0,0 +1,7 @@
1
+export class Candidate {
2
+    id: string;
3
+    firstname: string;
4
+    lastname: string;
5
+    emails: [];
6
+}
7
+

+ 9
- 0
src/app/shared/services/candidate.service.ts Visa fil

@@ -0,0 +1,9 @@
1
+import { Injectable } from '@angular/core';
2
+
3
+@Injectable({
4
+  providedIn: 'root'
5
+})
6
+export class CandidateService {
7
+
8
+  constructor() { }
9
+}

+ 19
- 0
src/app/shared/services/node.service.ts Visa fil

@@ -0,0 +1,19 @@
1
+import { HttpClient } from '@angular/common/http';
2
+import { Injectable } from '@angular/core';
3
+
4
+import { TreeNode } from 'primeng/api';
5
+
6
+@Injectable({
7
+  providedIn: 'root'
8
+})
9
+export class NodeService {
10
+
11
+    constructor(private http: HttpClient) { }
12
+
13
+    getFiles() {
14
+    return this.http.get<any>('assets/demo/data/files.json')
15
+      .toPromise()
16
+      .then(res => res.data as TreeNode[]);
17
+    }
18
+
19
+}

+ 161
- 0
src/appdemo.scss Visa fil

@@ -0,0 +1,161 @@
1
+@import "assets/demo/flags/flags.css";
2
+
3
+.layout-topbar {
4
+    .notifications {
5
+        .layout-topbar-action-panel {
6
+            img {
7
+                width: 32px;
8
+                height: 32px;
9
+            }
10
+
11
+            .layout-topbar-action-item {
12
+                border-bottom: 1px solid var(--divider-color);
13
+
14
+                &:last-child {
15
+                    border-bottom: 0 none;
16
+                }
17
+            }
18
+        }
19
+    }
20
+
21
+    .app {
22
+        .layout-topbar-action-panel {
23
+            a {
24
+                padding: .5rem 0;
25
+
26
+                i {
27
+                    width: 42px;
28
+                    height: 42px;
29
+                    border: 1px solid transparent;
30
+                    border-radius: 50%;
31
+                    margin: .5rem 0;
32
+                    display: flex;
33
+                    align-items: center;
34
+                    justify-content: center;
35
+                }
36
+            }
37
+        }
38
+    }
39
+}
40
+
41
+.layout-rightmenu {
42
+    .header {
43
+        padding-bottom: .5rem;
44
+        margin-bottom: .714rem;
45
+        border-bottom: 1px solid var(--divider-color);
46
+    }
47
+
48
+    .online-members {
49
+        img {
50
+            width: 32px;
51
+        }
52
+
53
+        b {
54
+            color: var(--primary-color)
55
+        }
56
+    }
57
+
58
+    .latest-activity {
59
+        i {
60
+            border: 1px solid transparent;
61
+            border-radius: 50px;
62
+            background-color: var(--surface-d);
63
+        }
64
+    }
65
+
66
+    .next-events {
67
+        ul {
68
+            margin: 0;
69
+            list-style-type: none;
70
+            padding: 0;
71
+
72
+            > li {
73
+                padding: .875rem .5rem;
74
+            }
75
+        }
76
+    }
77
+}
78
+
79
+.layout-help-page {
80
+    .questions {
81
+        &.p-accordion p-accordiontab {
82
+            .p-accordion-tab {
83
+                margin-top: 1rem;
84
+            }
85
+
86
+            &:first-child {
87
+                .p-accordion-tab {
88
+                    margin-top: 0;
89
+                }
90
+            }
91
+        }
92
+    }
93
+}
94
+
95
+.layout-invoice-page {
96
+    .p-invoice-datatable-responsive .p-datatable-tbody > tr > td .p-column-title {
97
+        display: none;
98
+    }
99
+
100
+    @media screen and (max-width: 40rem) {
101
+        .p-invoice-datatable-responsive {
102
+            .p-datatable-thead > tr > th,
103
+            .p-datatable-tfoot > tr > td {
104
+                display: none !important;
105
+            }
106
+
107
+            .p-datatable-tbody > tr > td {
108
+                text-align: left;
109
+                display: block;
110
+                width: 100%;
111
+                float: left;
112
+                clear: left;
113
+                border: 0 none;
114
+
115
+                .p-column-title {
116
+                    padding: .4rem;
117
+                    min-width: 30%;
118
+                    display: inline-block;
119
+                    margin: -.4em 1em -.4em -.4rem;
120
+                    font-weight: bold;
121
+                }
122
+
123
+                &:last-child {
124
+                    border-bottom: 1px solid var(--surface-d);
125
+                }
126
+            }
127
+        }
128
+    }
129
+}
130
+
131
+@media (min-width: 992px) {
132
+    .layout-menu-slim {
133
+        .layout-inline-menu {
134
+            .layout-inline-menu-action {
135
+                justify-content: center;
136
+
137
+                > span,
138
+                > i {
139
+                    display: none !important;
140
+                }
141
+            }
142
+
143
+            .layout-inline-menu-action-panel {
144
+                .layout-inline-menu-action-item {
145
+                    > a {
146
+                        justify-content: center;
147
+
148
+                        > i {
149
+                            font-size: 1.5rem;
150
+                            margin-right: 0 !important;
151
+                        }
152
+
153
+                        > span {
154
+                            display: none;
155
+                        }
156
+                    }
157
+                }
158
+            }
159
+        }
160
+    }
161
+}

+ 28
- 0
src/assets/demo/data/candidates.json Visa fil

@@ -0,0 +1,28 @@
1
+{
2
+	"data": [
3
+		{
4
+			"id": "1",
5
+			"firstName": "Tom",
6
+			"lastName": "Hanks",
7
+			"emails": [
8
+				{"email":"tom.hanks@natan.fr", "type":"profesionnal"},
9
+				{"email":"tom.hanks@gmail.com", "type":"personal"}
10
+			] 
11
+		},
12
+		{
13
+			"id": "2",
14
+			"firstName": "Denis",
15
+			"lastName": "Dupond",
16
+			"emails": [
17
+				{"email":"denis.dupond@natan.fr", "type":"profesionnal"},
18
+				{"email":"denis.dupond@gmail.com", "type":"personal"}
19
+			] 
20
+		},
21
+		{
22
+			"id": "3",
23
+			"firstName": "Gerard",
24
+			"lastName": "Jackson",
25
+			"emails": []
26
+		}
27
+	]
28
+}

+ 89
- 0
src/assets/demo/data/files.json Visa fil

@@ -0,0 +1,89 @@
1
+{
2
+    "data": [
3
+        {
4
+            "key": "0",
5
+            "label": "app",
6
+            "data": "App Folder",
7
+            "expanded":true,
8
+            "children": [
9
+                {
10
+                    "key": "0-0",
11
+                    "label": "pages",
12
+                    "data": "Pages Folder",
13
+                    "expanded":true,
14
+                    "children": [
15
+                        {
16
+                            "key": "0-0-0",
17
+                            "label": "candidate",
18
+                            "data": "Candidate Folder",
19
+                            "expanded":true,
20
+                            "children": [
21
+                                {"key": "0-0-0-0", "label": "candidate-list",  "data": "Candidate list Folder", "expanded":true, "children": [{"key": "0-0-0-0", "label": "candidate-list.service.ts"}]},
22
+                                {"key": "0-0-0-1", "label": "candidate-detail",  "data": "Candidate detail Folder","expanded":true, "children": []},
23
+                                {"key": "0-0-0-2", "label": "candidate-sidebar",  "data": "Candidate sidebar Folder","expanded":true, "children": []},
24
+                                {"key": "0-0-0-3", "label": "candidate-searchbar",  "data": "Candidate searchbar Folder","expanded":true, "children": []},
25
+                                {"key": "0-0-0-4", "label": "candidate.module.ts"}
26
+                            ]
27
+                        }
28
+                    ]
29
+                },
30
+                {
31
+                    "key": "0-1",
32
+                    "label": "shared",
33
+                    "data": "Shared Folder",
34
+                    "expanded":true,
35
+                    "children": [
36
+                        {
37
+                            "key": "0-1-0",
38
+                            "label": "models",
39
+                            "data": "Models Folder",
40
+                            "expanded":true,
41
+                            "children": [
42
+                                {"key": "0-1-0-0", "label": "candidate.ts"}
43
+                            ]
44
+                        },
45
+                        {
46
+                            "key": "0-2-0",
47
+                            "label": "services",
48
+                            "data": "Services Folder",
49
+                            "expanded":true,
50
+                            "children": [
51
+                                {"key": "0-2-0-0", "label": "candidate-service.ts"},
52
+                                {"key": "0-2-0-1", "label": "node.service.ts"}
53
+                            ]
54
+                        }
55
+                    ]
56
+                },
57
+                {
58
+                    "key": "0-1",
59
+                    "label": "app.menu.component.ts"
60
+                }
61
+            ]
62
+        },
63
+        {
64
+            "key": "1",
65
+            "label": "assets",
66
+            "data": "Assets Folder",
67
+            "expanded":true,
68
+            "children": [
69
+                {
70
+                    "key": "1-0",
71
+                    "label": "demo",
72
+                    "data": "Demo Folder",
73
+                    "expanded":true,
74
+                    "children": [
75
+                        {
76
+                            "key": "1-0-0",
77
+                            "label": "data",
78
+                            "data": "Data Folder",
79
+                            "expanded":true,
80
+                            "children": [
81
+                                {"key": "1-0-0-0", "label": "candidates.json"}
82
+                            ]
83
+                        }
84
+                    ]
85
+                }
86
+            ]
87
+        }
88
+    ]
89
+}

Binär
src/assets/demo/flags/flag_placeholder.png Visa fil


+ 1
- 0
src/assets/demo/flags/flags.css
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


Binär
src/assets/demo/flags/flags_responsive.png Visa fil


Binär
src/assets/demo/images/avatar/activity-1.png Visa fil


Binär
src/assets/demo/images/avatar/activity-2.png Visa fil


Binär
src/assets/demo/images/avatar/activity-3.png Visa fil


Binär
src/assets/demo/images/avatar/amyelsner.png Visa fil


Binär
src/assets/demo/images/avatar/annafali.png Visa fil


Binär
src/assets/demo/images/avatar/asiyajavayant.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-1.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-10.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-11.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-12.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-13.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-14.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-15.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-16.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-2.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-3.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-4.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-5.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-6.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-7.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-8.png Visa fil


Binär
src/assets/demo/images/avatar/avatar-9.png Visa fil


Binär
src/assets/demo/images/avatar/bernardodominic.png Visa fil


Binär
src/assets/demo/images/avatar/elwinsharvill.png Visa fil


Binär
src/assets/demo/images/avatar/ionibowcher.png Visa fil


Binär
src/assets/demo/images/avatar/ivanmagalhaes.png Visa fil


Binär
src/assets/demo/images/avatar/onyamalimba.png Visa fil


Binär
src/assets/demo/images/avatar/profile.jpg Visa fil


Binär
src/assets/demo/images/avatar/stephenshaw.png Visa fil


Binär
src/assets/demo/images/avatar/xuxuefeng.png Visa fil


Binär
src/assets/demo/images/galleria/galleria1.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria10.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria10s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria11.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria11s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria12.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria12s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria13.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria13s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria14.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria14s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria15.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria15s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria1s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria2.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria2s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria3.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria3s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria4.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria4s.jpg Visa fil


Binär
src/assets/demo/images/galleria/galleria5.jpg Visa fil


+ 0
- 0
src/assets/demo/images/galleria/galleria5s.jpg Visa fil


Vissa filer visades inte eftersom för många filer har ändrats

Powered by TurnKey Linux.