├── .circleci
└── config.yml
├── .editorconfig
├── .github
└── FUNDING.yml
├── .gitignore
├── .htmlhintrc
├── .stylelintrc
├── .travis.yml
├── .yo-rc.json
├── CODE_OF_CONDUCT.md
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── angular.json
├── assets
├── MDPI_SCREEN.png
├── angular-material-extensions-logo.png
└── angular-material-extensions-logo.svg
├── commitlint.config.js
├── coverage.lcov
├── docs
├── analytics.md
├── backend-proxy.md
├── coding-guides
│ ├── angular.md
│ ├── e2e-tests.md
│ ├── html.md
│ ├── sass.md
│ ├── typescript.md
│ └── unit-tests.md
├── corporate-proxy.md
├── i18n.md
├── readme.md
├── routing.md
└── updating.md
├── e2e
├── protractor.conf.js
├── src
│ ├── app.e2e-spec.ts
│ └── app.po.ts
└── tsconfig.e2e.json
├── ngsw-config.json
├── package-lock.json
├── package.json
├── prerender.ts
├── proxy.conf.js
├── server.ts
├── src
├── app
│ ├── about
│ │ ├── about-routing.module.ts
│ │ ├── about.component.html
│ │ ├── about.component.scss
│ │ ├── about.component.spec.ts
│ │ ├── about.component.ts
│ │ └── about.module.ts
│ ├── app-routing.module.ts
│ ├── app.component.html
│ ├── app.component.scss
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── app.server.module.ts
│ ├── components
│ │ ├── about
│ │ │ ├── about.component.html
│ │ │ ├── about.component.scss
│ │ │ ├── about.component.spec.ts
│ │ │ └── about.component.ts
│ │ ├── home
│ │ │ ├── home-routing.module.ts
│ │ │ ├── home.component.html
│ │ │ ├── home.component.scss
│ │ │ ├── home.component.spec.ts
│ │ │ ├── home.component.ts
│ │ │ ├── home.module.ts
│ │ │ ├── quote.service.spec.ts
│ │ │ └── quote.service.ts
│ │ ├── project-dialog
│ │ │ ├── project-dialog.component.html
│ │ │ ├── project-dialog.component.scss
│ │ │ ├── project-dialog.component.spec.ts
│ │ │ └── project-dialog.component.ts
│ │ └── shell
│ │ │ ├── header
│ │ │ ├── header.component.html
│ │ │ ├── header.component.scss
│ │ │ ├── header.component.spec.ts
│ │ │ └── header.component.ts
│ │ │ ├── shell.component.html
│ │ │ ├── shell.component.scss
│ │ │ ├── shell.component.spec.ts
│ │ │ ├── shell.component.ts
│ │ │ ├── shell.module.spec.ts
│ │ │ ├── shell.module.ts
│ │ │ ├── shell.service.spec.ts
│ │ │ └── shell.service.ts
│ ├── core
│ │ ├── core.module.ts
│ │ ├── http
│ │ │ ├── api-prefix.interceptor.spec.ts
│ │ │ ├── api-prefix.interceptor.ts
│ │ │ ├── cache.interceptor.spec.ts
│ │ │ ├── cache.interceptor.ts
│ │ │ ├── error-handler.interceptor.spec.ts
│ │ │ ├── error-handler.interceptor.ts
│ │ │ ├── http-cache.service.spec.ts
│ │ │ ├── http-cache.service.ts
│ │ │ ├── http.service.spec.ts
│ │ │ └── http.service.ts
│ │ ├── i18n.service.spec.ts
│ │ ├── i18n.service.ts
│ │ ├── index.ts
│ │ ├── logger.service.spec.ts
│ │ ├── logger.service.ts
│ │ └── route-reusable-strategy.ts
│ ├── home
│ │ ├── home-routing.module.ts
│ │ ├── home.component.html
│ │ ├── home.component.scss
│ │ ├── home.component.spec.ts
│ │ ├── home.component.ts
│ │ ├── home.module.ts
│ │ ├── quote.service.spec.ts
│ │ └── quote.service.ts
│ ├── material.module.ts
│ ├── shared
│ │ ├── index.ts
│ │ ├── loader
│ │ │ ├── loader.component.html
│ │ │ ├── loader.component.scss
│ │ │ ├── loader.component.spec.ts
│ │ │ └── loader.component.ts
│ │ └── shared.module.ts
│ └── shell
│ │ ├── header
│ │ ├── header.component.html
│ │ ├── header.component.scss
│ │ ├── header.component.spec.ts
│ │ └── header.component.ts
│ │ ├── shell.component.html
│ │ ├── shell.component.scss
│ │ ├── shell.component.spec.ts
│ │ ├── shell.component.ts
│ │ ├── shell.module.spec.ts
│ │ ├── shell.module.ts
│ │ ├── shell.service.spec.ts
│ │ └── shell.service.ts
├── apple-touch-icon.png
├── assets
│ ├── icons
│ │ ├── facebook.svg
│ │ ├── github-circle.svg
│ │ ├── linkedin.svg
│ │ └── twitter.svg
│ ├── images
│ │ └── icons
│ │ │ ├── icon-128x128.png
│ │ │ ├── icon-144x144.png
│ │ │ ├── icon-152x152.png
│ │ │ ├── icon-192x192.png
│ │ │ ├── icon-384x384.png
│ │ │ ├── icon-512x512.png
│ │ │ ├── icon-72x72.png
│ │ │ └── icon-96x96.png
│ ├── img
│ │ ├── portfolio
│ │ │ ├── cabin.png
│ │ │ ├── cake.png
│ │ │ ├── circus.png
│ │ │ ├── game.png
│ │ │ ├── safe.png
│ │ │ └── submarine.png
│ │ └── profile.png
│ ├── manifest.json
│ ├── ngx-rocket-logo.png
│ └── pdf
│ │ └── graduate_software_engineer.pdf
├── browserslist
├── config.interface.ts
├── config.ts
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── karma.conf.js
├── main.scss
├── main.server.ts
├── main.ts
├── manifest.json
├── polyfills.ts
├── robots.txt
├── test.ts
├── theme
│ ├── theme-variables.scss
│ └── theme.scss
├── translations
│ ├── de-DE.json
│ ├── en-US.json
│ └── fr-FR.json
├── tsconfig.app.json
├── tsconfig.server.json
├── tsconfig.spec.json
└── typings.d.ts
├── static.paths.ts
├── tsconfig.json
├── tslint.json
└── webpack.server.config.js
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | job_defaults: &job_defaults
4 | docker:
5 | - image: circleci/node:10-browsers
6 | environment:
7 | CHROME_BIN: '/usr/bin/google-chrome'
8 | working_directory: ~/project/repo
9 |
10 | cache_key: &cache_key angular-material-extension/freelancer-theme-deps-cache-{{ .Branch }}-{{ checksum "package-lock.json" }}
11 | dist_key: &dist_key angular-material-extension/freelancer-theme-dist-{{ .Revision }}
12 |
13 | jobs:
14 | install:
15 | <<: *job_defaults
16 | steps:
17 | - checkout
18 | - restore_cache:
19 | key: *cache_key
20 | - run:
21 | name: install-dependencies
22 | command: npm ci
23 | - save_cache:
24 | key: *cache_key
25 | paths:
26 | - node_modules
27 |
28 | lint:
29 | <<: *job_defaults
30 | steps:
31 | - checkout
32 | - restore_cache:
33 | key: *cache_key
34 | - run:
35 | name: lint
36 | command: npm run lint
37 |
38 | test-app:
39 | <<: *job_defaults
40 | steps:
41 | - checkout
42 | - restore_cache:
43 | key: *cache_key
44 | - restore_cache:
45 | key: *dist_key
46 | - run:
47 | name: test
48 | command: npm run test:ci
49 |
50 | codecov:
51 | <<: *job_defaults
52 | steps:
53 | - checkout
54 | - restore_cache:
55 | key: *cache_key
56 | - restore_cache:
57 | key: *dist_key
58 | - run:
59 | name: codecov
60 | command: npx codecov
61 |
62 | build-prerender-app:
63 | <<: *job_defaults
64 | steps:
65 | - checkout
66 | - restore_cache:
67 | key: *cache_key
68 | - run:
69 | name: test
70 | command: npm run build:prerender:ci
71 | - save_cache:
72 | key: *dist_key
73 | paths:
74 | - dist
75 |
76 | release:
77 | <<: *job_defaults
78 | steps:
79 | - checkout
80 | - restore_cache:
81 | key: *cache_key
82 | - restore_cache:
83 | key: *dist_key
84 | - run:
85 | name: release
86 | command: npm run semantic-release || true
87 |
88 | deploy-app:
89 | <<: *job_defaults
90 | steps:
91 | - checkout
92 | - restore_cache:
93 | key: *cache_key
94 | - restore_cache:
95 | key: *dist_key
96 | - run:
97 | name: deploy-app
98 | command: npm run deploy:demo
99 |
100 | workflows:
101 | version: 2
102 | build-test-release:
103 | jobs:
104 | - install
105 | - lint:
106 | requires:
107 | - install
108 | # - test-app:
109 | # requires:
110 | # - install
111 | # - codecov:
112 | # requires:
113 | # - test-app
114 | - release:
115 | requires:
116 | - lint
117 | filters:
118 | branches:
119 | only: master
120 | - build-prerender-app:
121 | requires:
122 | - release
123 | # - lint
124 | # - test-app
125 | - deploy-app:
126 | requires:
127 | - build-prerender-app
128 | filters:
129 | branches:
130 | only: master
131 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 | end_of_line = lf
11 | max_line_length = 120
12 |
13 | [*.md]
14 | max_line_length = off
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: angular-material-extensions
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
8 | liberapay: # Replace with a single Liberapay username
9 | issuehunt: # Replace with a single IssueHunt username
10 | otechie: # Replace with a single Otechie username
11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12 | custom: ['https://github.com/AnthonyNahas','anahas.de']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # Compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # Dependencies
9 | /node_modules
10 |
11 | # Cordova
12 | /www
13 | /plugins
14 | /platforms
15 |
16 | # IDEs and editors
17 | .idea/*
18 | !.idea/runConfigurations/
19 | !.idea/codeStyleSettings.xml
20 | .project
21 | .classpath
22 | .c9/
23 | *.launch
24 | .settings/
25 | xcuserdata/
26 | *.sublime-workspace
27 |
28 | # IDE - VSCode
29 | .vscode/*
30 | !.vscode/settings.json
31 | !.vscode/tasks.json
32 | !.vscode/launch.json
33 | !.vscode/extensions.json
34 |
35 | # Maven
36 | /target
37 | /log
38 |
39 | # Misc
40 | /.sass-cache
41 | /connect.lock
42 | /coverage
43 | /libpeerconnection.log
44 | npm-debug.log
45 | yarn-error.log
46 | testem.log
47 | /typings
48 | /reports
49 | /src/translations/template.*
50 | /src/environments/.env.*
51 |
52 | # System Files
53 | .DS_Store
54 | Thumbs.db
55 |
--------------------------------------------------------------------------------
/.htmlhintrc:
--------------------------------------------------------------------------------
1 | {
2 | "tagname-lowercase": false,
3 | "attr-lowercase": false,
4 | "attr-value-double-quotes": true,
5 | "tag-pair": true,
6 | "spec-char-escape": true,
7 | "id-unique": true,
8 | "src-not-empty": true,
9 | "attr-no-duplication": true,
10 | "title-require": true,
11 | "tag-self-close": true,
12 | "head-script-disabled": true,
13 | "doctype-html5": true,
14 | "id-class-value": "dash",
15 | "style-disabled": true,
16 | "inline-style-disabled": true,
17 | "inline-script-disabled": true,
18 | "space-tab-mixed-disabled": "true",
19 | "id-class-ad-disabled": true,
20 | "attr-unsafe-chars": true
21 | }
22 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "stylelint-config-standard",
4 | "stylelint-config-recommended-scss",
5 | "stylelint-config-prettier"
6 | ],
7 | "rules": {
8 | "font-family-name-quotes": "always-where-recommended",
9 | "function-url-quotes": [
10 | "always",
11 | {
12 | "except": ["empty"]
13 | }
14 | ],
15 | "selector-attribute-quotes": "always",
16 | "string-quotes": "double",
17 | "max-nesting-depth": 3,
18 | "selector-max-compound-selectors": 3,
19 | "selector-max-specificity": "0,3,2",
20 | "declaration-no-important": true,
21 | "at-rule-no-vendor-prefix": true,
22 | "media-feature-name-no-vendor-prefix": true,
23 | "property-no-vendor-prefix": true,
24 | "selector-no-vendor-prefix": true,
25 | "value-no-vendor-prefix": true,
26 | "no-empty-source": null,
27 | "selector-class-pattern": "[a-z-]+",
28 | "selector-id-pattern": "[a-z-]+",
29 | "selector-max-id": 0,
30 | "selector-no-qualifying-type": true,
31 | "selector-max-universal": 0,
32 | "selector-pseudo-element-no-unknown": [
33 | true,
34 | {
35 | "ignorePseudoElements": ["ng-deep"]
36 | }
37 | ],
38 | "unit-whitelist": ["px", "%", "em", "rem", "vw", "vh", "deg", "s"],
39 | "max-empty-lines": 2,
40 | "max-line-length": 120
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | dist: trusty
3 |
4 | #install google chrome, using addons
5 | addons:
6 | apt:
7 | sources:
8 | - google-chrome
9 | packages:
10 | - google-chrome-stable
11 |
12 | language: node_js
13 | node_js:
14 | - '10'
15 |
16 | branches:
17 | only:
18 | - master
19 | - /^greenkeeper/.*$/
20 |
21 | cache:
22 | directories:
23 | - node_modules
24 |
25 | before_script:
26 | - export DISPLAY=:99.0
27 | - sh -e /etc/init.d/xvfb start
28 | # - npm install --quiet -g gulp-cli
29 |
30 | #script: gulp test:ci
31 | script:
32 | # - ng test --watch false -cc
33 | # - npm run e2e
34 | - npm run build:prerender
35 |
36 | after_success: gulp coveralls
37 |
38 | deploy:
39 | provider: pages
40 | skip_cleanup: true
41 | github_token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
42 | local_dir: dist
43 | on:
44 | branch: master
45 |
--------------------------------------------------------------------------------
/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-ngx-rocket": {
3 | "version": "5.3.0",
4 | "props": {
5 | "location": "path",
6 | "appName": "freelancer-theme",
7 | "target": ["web"],
8 | "pwa": true,
9 | "ui": "material",
10 | "layout": "simple",
11 | "auth": false,
12 | "lazy": true,
13 | "angulartics": true,
14 | "analyticsProvider": "ga",
15 | "googleAnalyticsAccount": "",
16 | "prettier": true,
17 | "projectName": "freelancer-theme",
18 | "packageManager": "npm",
19 | "mobile": []
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at Anthony.na@hotmail.de. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | ### Bug Report or Feature Request (mark with an `x`)
6 |
7 | ```
8 | - [ ] bug report -> please search issues before submitting
9 | - [ ] feature request
10 | ```
11 |
12 | ### OS and Version?
13 |
14 |
17 |
18 | ### Versions
19 |
20 |
24 |
25 | ### Repro steps
26 |
27 |
32 |
33 | ### The log given by the failure
34 |
35 |
36 |
37 | ### Desired functionality
38 |
39 |
43 |
44 | ### Mention any other details that might be useful
45 |
46 |
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 angular-material-extensions
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "freelancer-theme": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {
12 | "@schematics/angular:component": {
13 | "styleext": "scss"
14 | }
15 | },
16 | "architect": {
17 | "build": {
18 | "builder": "@angular-devkit/build-angular:browser",
19 | "options": {
20 | "outputPath": "dist/browser",
21 | "index": "src/index.html",
22 | "main": "src/main.ts",
23 | "tsConfig": "src/tsconfig.app.json",
24 | "polyfills": "src/polyfills.ts",
25 | "assets": [
26 | "src/favicon.ico",
27 | "src/apple-touch-icon.png",
28 | "src/robots.txt",
29 | "src/manifest.json",
30 | "src/assets"
31 | ],
32 | "styles": ["src/main.scss", "node_modules/material-design-icons/iconfont/material-icons.css"],
33 | "scripts": []
34 | },
35 | "configurations": {
36 | "production": {
37 | "optimization": true,
38 | "outputHashing": "all",
39 | "sourceMap": false,
40 | "extractCss": true,
41 | "namedChunks": false,
42 | "aot": true,
43 | "extractLicenses": true,
44 | "vendorChunk": false,
45 | "buildOptimizer": true,
46 | "serviceWorker": true,
47 | "fileReplacements": [
48 | {
49 | "replace": "src/environments/environment.ts",
50 | "with": "src/environments/environment.prod.ts"
51 | }
52 | ]
53 | }
54 | }
55 | },
56 | "server": {
57 | "builder": "@angular-devkit/build-angular:server",
58 | "options": {
59 | "outputPath": "dist/server",
60 | "main": "src/main.server.ts",
61 | "tsConfig": "src/tsconfig.server.json"
62 | },
63 | "configurations": {
64 | "production": {
65 | "fileReplacements": [
66 | {
67 | "replace": "src/environments/environment.ts",
68 | "with": "src/environments/environment.prod.ts"
69 | }
70 | ]
71 | }
72 | }
73 | },
74 | "serve": {
75 | "builder": "@angular-devkit/build-angular:dev-server",
76 | "options": {
77 | "browserTarget": "freelancer-theme:build"
78 | },
79 | "configurations": {
80 | "production": {
81 | "browserTarget": "freelancer-theme:build:production"
82 | }
83 | }
84 | },
85 | "extract-i18n": {
86 | "builder": "@angular-devkit/build-angular:extract-i18n",
87 | "options": {
88 | "browserTarget": "freelancer-theme:build"
89 | }
90 | },
91 | "test": {
92 | "builder": "@angular-devkit/build-angular:karma",
93 | "options": {
94 | "main": "src/test.ts",
95 | "karmaConfig": "src/karma.conf.js",
96 | "polyfills": "src/polyfills.ts",
97 | "tsConfig": "src/tsconfig.spec.json",
98 | "scripts": [],
99 | "styles": ["src/main.scss", "node_modules/material-design-icons/iconfont/material-icons.css"],
100 | "assets": [
101 | "src/favicon.ico",
102 | "src/apple-touch-icon.png",
103 | "src/robots.txt",
104 | "src/manifest.json",
105 | "src/assets"
106 | ]
107 | }
108 | },
109 | "lint": {
110 | "builder": "@angular-devkit/build-angular:tslint",
111 | "options": {
112 | "tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"],
113 | "exclude": ["**/node_modules/**"]
114 | }
115 | }
116 | }
117 | },
118 | "freelancer-theme-e2e": {
119 | "root": "e2e",
120 | "projectType": "application",
121 | "architect": {
122 | "e2e": {
123 | "builder": "@angular-devkit/build-angular:protractor",
124 | "options": {
125 | "protractorConfig": "e2e/protractor.conf.js",
126 | "devServerTarget": "freelancer-theme:serve"
127 | }
128 | },
129 | "lint": {
130 | "builder": "@angular-devkit/build-angular:tslint",
131 | "options": {
132 | "tsConfig": ["e2e/tsconfig.e2e.json"],
133 | "exclude": ["**/node_modules/**"]
134 | }
135 | }
136 | }
137 | }
138 | },
139 | "defaultProject": "freelancer-theme"
140 | }
141 |
--------------------------------------------------------------------------------
/assets/MDPI_SCREEN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angular-material-extensions/freelancer-theme/616e447c3445d17580cdd5de25297f8bf5716089/assets/MDPI_SCREEN.png
--------------------------------------------------------------------------------
/assets/angular-material-extensions-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angular-material-extensions/freelancer-theme/616e447c3445d17580cdd5de25297f8bf5716089/assets/angular-material-extensions-logo.png
--------------------------------------------------------------------------------
/assets/angular-material-extensions-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] };
2 |
--------------------------------------------------------------------------------
/coverage.lcov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angular-material-extensions/freelancer-theme/616e447c3445d17580cdd5de25297f8bf5716089/coverage.lcov
--------------------------------------------------------------------------------
/docs/analytics.md:
--------------------------------------------------------------------------------
1 | # Analytics
2 |
3 | Analytics in this app are managed through the [Angulartics2](https://github.com/angulartics/angulartics2) library.
4 |
5 | It is already pre-configured to track page views, and provides examples to track events from both TypeScript code and HTML elements.
6 | Here is a quick usage documentation, you can read further information on the official website.
7 |
8 | ## Registering your provider
9 |
10 | Google Analytics is already registered as the project's analytics provider.
11 | Should you need to change the account identifier, you can do so in the call to `ga(...)` performed in the body of `index.html`.
12 |
13 | ## Tracking events
14 |
15 | ### Declarative event tracking
16 |
17 | The simplest way to do event tracking is by adding the attributes `angulartics2On`, `angularticsCategory` and `angularticsAction` to an HTML element.
18 | The homepage generated by the starter kit contains one such button.
19 | For reference, here is a UI-framework-agnostic example.
20 |
21 | ```html
22 |
29 | ```
30 |
31 | ### Using the API
32 |
33 | As an example, the application already comes configured to track its startup through an event.
34 | You may use the example as reference: it can be found in the first lines of `ngOnInit()` in `app.component.ts`.
35 |
36 | To access the API, inject your provider :
37 |
38 | ```typescript
39 | constructor(...
40 | private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics,
41 | ...)
42 | ```
43 |
44 | You may then use the `eventTrack` function:
45 |
46 | ```typescript
47 | this.angulartics2GoogleAnalytics.eventTrack('Something happened', {
48 | category: 'My category'
49 | });
50 | this.angulartics2GoogleAnalytics.eventTrack('Something else happened', {
51 | category: 'My other category',
52 | label: 'My custom label'
53 | });
54 | ```
55 |
--------------------------------------------------------------------------------
/docs/backend-proxy.md:
--------------------------------------------------------------------------------
1 | # Backend proxy
2 |
3 | Usually when working on a web application you consume data from custom-made APIs.
4 |
5 | To ease development with our development server integrating live reload while keeping your backend API calls working,
6 | we also have setup a backend proxy to redirect API calls to whatever URL and port you want. This allows you:
7 |
8 | - To develop frontend features without the need to run an API backend locally
9 | - To use a local development server without [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) issues
10 | - To debug frontend code with data from a remote testing platform directly
11 |
12 | ## How to configure
13 |
14 | In the root folder you will find a `proxy.conf.js`, containing the backend proxy configuration.
15 |
16 | The interesting part is there:
17 |
18 | ```js
19 | const proxyConfig = [
20 | {
21 | context: '/api',
22 | pathRewrite: { '^/api': '' },
23 | target: 'http://api.icndb.com',
24 | changeOrigin: true
25 | }
26 | ];
27 | ```
28 |
29 | This is where you can setup one or more proxy rules.
30 |
31 | For the complete set of options, see the `http-proxy-middleware`
32 | [documentation](https://github.com/chimurai/http-proxy-middleware#options).
33 |
34 | ### Corporate proxy support
35 |
36 | To allow external API calls redirection through a corporate proxy, you will also find a `setupForCorporateProxy()`
37 | function in the proxy configuration file. By default, this method configures a corporate proxy agent based on the
38 | `HTTP_PROXY` environment variable, see the [corporate proxy documentation](corporate-proxy.md) for more details.
39 |
40 | If you need to, you can further customize this function to fit the network of your working environment.
41 |
42 | If your corporate proxy use a custom SSL certificate, your may need to add the `secure: false` option to your
43 | backend proxy configuration.
44 |
--------------------------------------------------------------------------------
/docs/coding-guides/e2e-tests.md:
--------------------------------------------------------------------------------
1 | # End-to-end tests coding guide
2 |
3 | End-to-end (E2E for short) tests are meant to test the behavior of your application, from start to finish.
4 |
5 | While unit tests are the first choice for catching bugs and regression on individual components, it is a good idea to
6 | complement them with test cases covering the integration between the individual components, hence the need for E2E
7 | tests.
8 |
9 | These tests use [Protractor](https://github.com/angular/protractor), which is a framework built for Angular on top of
10 | [Selenium](https://github.com/SeleniumHQ/selenium) to control browsers and simulate user inputs.
11 | [Jasmine](http://jasmine.github.io) is used as the base test framework.
12 |
13 | ## Good practices
14 |
15 | - Avoid whenever possible inter-dependencies between your E2E tests
16 | - Run E2E tests on your continuous integration server against different browsers
17 | - If you use an Agile methodology, cover each user story acceptance factors with an E2E test
18 |
19 | ## Page objects
20 |
21 | E2E tests should follow the _[Page Object](https://github.com/SeleniumHQ/selenium/wiki/PageObjects)_ pattern.
22 |
23 | #### What is a page object?
24 |
25 | A page object:
26 |
27 | - Models the objects on a page under test:
28 | - _Properties_ wrap page elements
29 | - _Methods_ wrap code that interacts with the page elements
30 | - Simplifies the test scripts
31 | - Reduces the amount of duplicated code
32 |
33 | If the UI changes, the fix only needs to be applied in one place.
34 |
35 | #### How to define a page object
36 |
37 | ```typescript
38 | // login.po.ts
39 | import { browser, element, by } from 'protractor';
40 |
41 | export class LoginPage {
42 | emailInput = element(by.css('input[name=^"email"]'));
43 | passwordInput = element(by.css('input[name=^"password"]'));
44 | loginButton = element(by.css('button[(click)^="login"]'));
45 | registerButton = element(by.css('button[(click)^="register"]'));
46 |
47 | navigateTo() {
48 | return browser.get('/');
49 | }
50 |
51 | getGreetingText() {
52 | return element(by.css('.greeting')).getText();
53 | }
54 | }
55 | ```
56 |
57 | #### How to use a page object
58 |
59 | ```typescript
60 | // login.e2e-spec.ts
61 | import { LoginPage } from './login.po';
62 |
63 | describe('Login', () => {
64 | let page: LoginPage;
65 |
66 | beforeEach(() => {
67 | page = new LoginPage();
68 | page.navigateTo();
69 | });
70 |
71 | it('should navigate to the register page when the register button is clicked', () => {
72 | page.registerButton.click();
73 |
74 | expect(browser.getCurrentUrl()).toContain('/register');
75 | });
76 |
77 | it('should allow a user to log in', () => {
78 | page.emailInput.sendKeys('test@mail.com');
79 | page.passwordInput.sendKeys('abc123');
80 | page.loginButton.click();
81 |
82 | expect(page.getGreetingText()).toContain('Welcome, Test User');
83 | });
84 | });
85 | ```
86 |
87 | ## Credits
88 |
89 | Parts of this guide were freely inspired by this
90 | [presentation](https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ).
91 |
--------------------------------------------------------------------------------
/docs/coding-guides/html.md:
--------------------------------------------------------------------------------
1 | # HTML coding guide
2 |
3 | ## Naming conventions
4 |
5 | - Everything should be named in `kebab-case` (lowercase words separated with a `-`): tags, attributes, IDs, etc,
6 | **except for everything bound to Angular** such variables, directives or events which should be in `camelCase`
7 | - File names should always be in `kebab-case`
8 |
9 | ## Coding rules
10 |
11 | - Use HTML5 doctype: ``
12 | - Use HTML [semantic elements](https://developer.mozilla.org/docs/Web/HTML/Sections_and_Outlines_of_an_HTML5_document)
13 | - Use double quotes `"` around attribute values in tags
14 | - Use a new line for every block, list, or table element, and indent every such child element
15 | - Clearly Separate structure (HTML) from presentation (CSS) from behavior (JavaScript):
16 | - Never use inline CSS or JavaScript
17 | - Keep any logic out of the HTML
18 | - `type` attribute for stylesheets and script tags should be omitted
19 |
20 | ## Common pitfalls
21 |
22 | - **Block**-type tags cannot be nested inside **inline**-type tags: a `
` tag cannot be nested in a ``.
23 | This rule also applies regarding the `display` value of an element.
24 | - HTML is **not** XML: empty tags cannot be self-closing and will result in improper results
25 | - `` will be interpreted as a simple `
` without closing tag!
26 | - The only tags that allows self-closing are the one that does not require a closing tag in first place:
27 | these are the void elements that do not not accept content ` `, ``, ``, ``, ``, ``
28 | (and others).
29 |
30 | ## Templates
31 |
32 | In accordance with the [Angular style guide](https://angular.io/guide/styleguide), HTML templates should be extracted in
33 | separate files, when more than 3 lines.
34 |
35 | Only use inline templates sparingly in very simple components with less than 3 lines of HTML.
36 |
37 | ## Enforcement
38 |
39 | Coding rules enforcement and basic sanity checks are done in this project by [HTMLHint](http://htmlhint.com).
40 |
--------------------------------------------------------------------------------
/docs/coding-guides/sass.md:
--------------------------------------------------------------------------------
1 | # Sass coding guide
2 |
3 | [Sass](http://sass-lang.com) is a superset of CSS, which brings a lot of developer candy to help scaling CSS in large
4 | projects and keeping it maintainable.
5 |
6 | The main benefits of using Sass over plain CSS are _variables_, _nesting_ and _mixins_, see the
7 | [basics guide](http://sass-lang.com/guide) for more details.
8 |
9 | > Note that this project use the newer, CSS-compatible **SCSS** syntax over the old
10 | > [indented syntax](http://sass-lang.com/documentation/file.INDENTED_SYNTAX.html).
11 |
12 | ## Naming conventions
13 |
14 | - In the CSS world, everything should be named in `kebab-case` (lowercase words separated with a `-`).
15 | - File names should always be in `kebab-case`
16 |
17 | ## Coding rules
18 |
19 | - Use single quotes `'` for strings
20 | - Use this general nesting hierarchy when constructing your styles:
21 |
22 | ```scss
23 | // The base component class acts as the namespace, to avoid naming and style collisions
24 | .my-component {
25 | // Put here all component elements (flat)
26 | .my-element {
27 | // Use a third-level only for modifiers and state variations
28 | &.active { ... }
29 | }
30 | }
31 | ```
32 |
33 | Note that with
34 | [Angular view encapsulation](https://angular.io/docs/ts/latest/guide/component-styles.html#!#view-encapsulation),
35 | the first "namespace" level of nesting is not necessary as Angular takes care of the scoping for avoid collisions.
36 |
37 | > As a side note, we are aware of the [BEM naming approach](https://en.bem.info/tools/bem/bem-naming/), but we found
38 | > it impractical for large projects. The nesting approach has drawbacks such as increased specificity, but it helps
39 | > keeping everything nicely organized, and more importantly, _scoped_.
40 |
41 | Also keep in mind this general rules:
42 |
43 | - Always use **class selectors**, never use ID selectors and avoid element selectors whenever possible
44 | - No more than **3 levels** of nesting
45 | - No more than **3 qualifiers**
46 |
47 | ## Best practices
48 |
49 | - Use object-oriented CSS (OOCSS):
50 |
51 | - Factorize common code in base class, and extend it, for example:
52 |
53 | ```scss
54 | // Base button class
55 | .btn { ... }
56 |
57 | // Color variation
58 | .btn-warning { ... }
59 |
60 | // Size variation
61 | .btn-small { ... }
62 | ```
63 |
64 | - Try to name class by semantic, not style nor function for better reusability:
65 | Use `.btn-warning`, not `btn-orange` nor `btn-cancel`
66 | - Avoid undoing style, refactor using common base classes and extensions
67 |
68 | - Keep your style scoped
69 |
70 | - Clearly separate **global** (think _framework_) and **components** style
71 | - Global style should only go in `src/theme/`, never in components
72 | - Avoid style interactions between components, if some style may need to be shared, refactor it as a framework
73 | component in put it in your global theme.
74 | - Avoid using wider selectors than needed: always use classes if you can!
75 |
76 | - Avoid rules multiplication
77 |
78 | - The less CSS the better, factorize rules whenever it's possible
79 | - CSS is code, and like any code frequent refactoring is healthy
80 |
81 | - When ugly hacks cannot be avoided, create an explicit `src/hacks.scss` file and put it in:
82 | - These ugly hacks should only be **temporary**
83 | - Each hack should be documented with the author name, the problem and hack reason
84 | - Limit this file to a reasonable length (~100 lines) and refactor hacks with proper solutions when the limit is
85 | reached.
86 |
87 | ## Pitfalls
88 |
89 | - Never use the `!important` keyword. Ever.
90 | - Never use **inline** style in html, even _just for debugging_ (because we **KNOW** it will end up in your commit)
91 |
92 | ## Browser compatibility
93 |
94 | You should never use browser-specific prefixes in your code, as [autoprefixer](https://github.com/postcss/autoprefixer)
95 | takes care of that part for you during the build process.
96 | You just need to declare which browsers you target in the [`browserslist`](https://github.com/ai/browserslist) file.
97 |
98 | ## Enforcement
99 |
100 | Coding rules are enforced in this project with [stylelint](https://stylelint.io).
101 | This tool also checks the compatibility of the rules used against the browsers you are targeting (specified in the
102 | [`browserslist`](https://github.com/ai/browserslist) file), via [doiuse](https://github.com/anandthakker/doiuse).
103 |
--------------------------------------------------------------------------------
/docs/coding-guides/typescript.md:
--------------------------------------------------------------------------------
1 | # TypeScript coding guide
2 |
3 | [TypeScript](http://www.typescriptlang.org) is a superset of JavaScript that greatly helps building large web
4 | applications.
5 |
6 | Coding conventions and best practices comes from the
7 | [TypeScript guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines), and are also detailed in the
8 | [TypeScript Deep Dive Style Guide](https://basarat.gitbooks.io/typescript/content/docs/styleguide/styleguide.html).
9 | In addition, this project also follows the general [Angular style guide](https://angular.io/guide/styleguide).
10 |
11 | ## Naming conventions
12 |
13 | - Use `PascalCase` for types, classes, interfaces, constants and enum values.
14 | - Use `camelCase` for variables, properties and functions
15 | - Avoid prefixing interfaces with a capital `I`, see [Angular style guide](https://angular.io/guide/styleguide#!#03-03)
16 | - Do not use `_` as a prefix for private properties. An exception can be made for backing fields like this:
17 | ```typescript
18 | private _foo: string;
19 | get foo() { return this._foo; } // foo is read-only to consumers
20 | ```
21 |
22 | ## Ordering
23 |
24 | - Within a file, type definitions should come first
25 | - Within a class, these priorities should be respected:
26 | - Properties comes before functions
27 | - Static symbols comes before instance symbols
28 | - Public symbols comes before private symbols
29 |
30 | ## Coding rules
31 |
32 | - Use single quotes `'` for strings
33 | - Always use strict equality checks: `===` and `!==` instead of `==` or `!=` to avoid comparison pitfalls (see
34 | [JavaScript equality table](https://dorey.github.io/JavaScript-Equality-Table/)).
35 | The only accepted usage for `==` is when you want to check a value against `null` or `undefined`.
36 | - Use `[]` instead of `Array` constructor
37 | - Use `{}` instead of `Object` constructor
38 | - Always specify types for function parameters and returns (if applicable)
39 | - Do not export types/functions unless you need to share it across multiple components
40 | - Do not introduce new types/values to the global namespace
41 | - Use arrow functions over anonymous function expressions
42 | - Only surround arrow function parameters when necessary.
43 | For example, `(x) => x + x` is wrong but the following are correct:
44 | - `x => x + x`
45 | - `(x, y) => x + y`
46 | - `(x: T, y: T) => x === y`
47 |
48 | ## Definitions
49 |
50 | In order to infer types from JavaScript modules, TypeScript language supports external type definitions. They are
51 | located in the `node_modules/@types` folder.
52 |
53 | To manage type definitions, use standard `npm install|update|remove` commands.
54 |
55 | ## Enforcement
56 |
57 | Coding rules are enforced in this project via [TSLint](https://github.com/palantir/tslint).
58 | Angular-specific rules are also enforced via the [Codelyzer](https://github.com/mgechev/codelyzer) rule extensions.
59 |
60 | ## Learn more
61 |
62 | The read of [TypeScript Deep Dive](https://basarat.gitbooks.io/typescript) is recommended, this is a very good
63 | reference book for TypeScript (and also open-source).
64 |
--------------------------------------------------------------------------------
/docs/coding-guides/unit-tests.md:
--------------------------------------------------------------------------------
1 | # Unit tests coding guide
2 |
3 | The main objective of unit tests is to detect regressions and to help you design software components. A suite of
4 | _good_ unit tests can be _immensely_ valuable for your project and makes it easier to refactor and expand your code.
5 | But keep in mind that a suite of _bad_ unit tests can also be _immensely_ painful, and hurt your development by
6 | inhibiting your ability to refactor or alter your code in any way.
7 |
8 | ## What to test?
9 |
10 | Everything! But if you need priorities, at least all business logic code must be tested: services, helpers, models...
11 | Shared directives/components should also be covered by unit tests, if you do not have the time to test every single
12 | component.
13 |
14 | Keep in mind that component unit tests should not overlap with [end-to-end tests](e2e-tests.md): while unit the tests
15 | cover the isolated behavior of the component bindings and methods, the end-to-end tests in opposition should cover the
16 | integration and interactions with other app components based on real use cases scenarios.
17 |
18 | ## Good practices
19 |
20 | - Name your tests cleanly and consistently
21 | - Do not only test nominal cases, the most important tests are the one covering the edge cases
22 | - Each test should be independent to all the others
23 | - Avoid unnecessary assertions: it's counter-productive to assert anything covered by another test, it just increase
24 | pointless failures and maintenance workload
25 | - Test only one code unit at a time: if you cannot do this, it means you have an architecture problem in your app
26 | - Mock out all external dependencies and state: if there is too much to mock, it is often a sign that maybe you
27 | should split your tested module into several more independent modules
28 | - Clearly separate or identify these 3 stages of each unit test (the _3A_): _arrange_, _act_ and _assert_
29 | - When you fix a bug, add a test case for it to prevent regression
30 |
31 | ## Pitfalls
32 |
33 | - Sometimes your architecture might mean your code modify static variables during unit tests. Avoid this if you can,
34 | but if you can't, at least make sure each test resets the relevant statics before and after your tests.
35 | - Don’t unit-test configuration settings
36 | - Improving test coverage is good, but having meaningful tests is better: start with the latter first, and **only after
37 | essential features of your code unit are tested**, your can think of improving the coverage.
38 |
39 | ## Unit testing with Angular
40 |
41 | A good starting point for learning is the official
42 | [testing guide](https://angular.io/docs/ts/latest/guide/testing.html).
43 |
44 | But as you will most likely want to go bit further in real world apps, these
45 | [example test snippets](https://gist.github.com/wkwiatek/e8a4a9d92abc4739f04f5abddd3de8a7) are also very helpful to
46 | learn how to cover most common testing use cases.
47 |
--------------------------------------------------------------------------------
/docs/corporate-proxy.md:
--------------------------------------------------------------------------------
1 | # Working behind a corporate proxy
2 |
3 | ## Environment
4 |
5 | Most tools (including npm and git) use the `HTTP_PROXY` and `HTTPS_PROXY` environment variables to work with a
6 | corporate proxy.
7 |
8 | ### Windows
9 |
10 | In Windows environments, add the `HTTP_PROXY` and `HTTPS_PROXY` system environment variable, with these values:
11 |
12 | - HTTP_PROXY: `http://:@:`
13 | - HTTPS_PROXY: `%HTTP_PROXY%`
14 |
15 | ### Unix
16 |
17 | Add these lines to your `~/.bash_profile` or `~/.profile`:
18 |
19 | ```sh
20 | export HTTP_PROXY="http://:@:"
21 | export HTTPS_PROXY="$HTTP_PROXY"
22 | ```
23 |
24 | ## Proxy with SSL custom certificate
25 |
26 | Some proxy like **zscaler** use a custom SSL certificate to inspect request, which may cause npm commands to fail.
27 |
28 | To solve this problem, you can disable the `strict-ssl` option in npm.
29 |
30 | ## Proxy exceptions
31 |
32 | If you need to access repositories on your local network that should bypass proxy, set the `NO_PROXY` environment
33 | variable, in the same way as `HTTP_PROXY`:
34 |
35 | ### Windows
36 |
37 | - NO_PROXY: `127.0.0.1, localhost, `
38 |
39 | ### Unix
40 |
41 | ```sh
42 | export NO_PROXY="127.0.0.1, localhost, "
43 | ```
44 |
45 | ### Npm
46 |
47 | Run this command in your project directory:
48 |
49 | ```sh
50 | npm set strict-ssl false
51 | ```
52 |
--------------------------------------------------------------------------------
/docs/i18n.md:
--------------------------------------------------------------------------------
1 | # I18n
2 |
3 | The internationalization of the application is managed by [ngx-translate](https://github.com/ngx-translate/core).
4 |
5 | ## Adding translatable strings
6 |
7 | ### In HTML templates
8 |
9 | Use the `translate` directive on an HTML element to automatically translate its content:
10 |
11 | ```html
12 | This text will be translated.
13 | ```
14 |
15 | You can also use the `translate` pipe if needed:
16 |
17 | ```html
18 |
19 | ```
20 |
21 | ### In TypeScript code
22 |
23 | If you need to translate strings in JavaScript code, import the `TranslateService` dependency and use the asynchronous
24 | `get()` method:
25 |
26 | ```typescript
27 | let title;
28 | translateService.get('My page title').subscribe((res: string) => {
29 | title = res;
30 | });
31 | ```
32 |
33 | ## Extracting strings to translate
34 |
35 | Once you are ready to translate your app, just run `npm run translations:extract`.
36 | It will create a `template.json` file in the `src/translations` folder.
37 |
38 | You can then use any text or code editor to generate the `.json` files for each of your supported languages, and put
39 | them in the `src/translations` folder.
40 |
41 | Do no forget to edit the files in `src/environment` to add the supported languages of your application.
42 |
43 | ### Marking strings for extraction
44 |
45 | If strings are not directly passed to `translateService` or put in HTML templates, they may be missing from the
46 | extraction process.
47 |
48 | For these cases, you have to use the dummy `extract()` function:
49 |
50 | ```typescript
51 | import { extract } from './core/i18n.service';
52 |
53 | function toBeTranslatedLater() {
54 | return extract('A string to be translated');
55 | }
56 | ```
57 |
58 | Strings marked like this will then be properly extracted.
59 |
--------------------------------------------------------------------------------
/docs/readme.md:
--------------------------------------------------------------------------------
1 | # freelancer-theme
2 |
3 | Welcome to the project documentation!
4 |
5 | Use `npm run docs` for easier navigation.
6 |
7 | ## Available documentation
8 |
9 | [[index]]
10 |
--------------------------------------------------------------------------------
/docs/routing.md:
--------------------------------------------------------------------------------
1 | # Browser routing
2 |
3 | To allow navigation without triggering a server request, Angular now use by default the
4 | [HTML5 pushState](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries)
5 | API enabling natural URL style (like `localhost:4200/home/`), in opposition to Angular 1 which used the _hashbang_ hack
6 | routing style (like `localhost:4200/#/home/`).
7 |
8 | This change has several consequences you should know of, be sure to read the
9 | [browser URL styles](https://angular.io/docs/ts/latest/guide/router.html#!#browser-url-styles) notice to fully
10 | understand the differences between the two approaches.
11 |
12 | In short:
13 |
14 | - It is only supported on modern browsers (IE10+), a [polyfill](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#html5-history-api-pushstate-replacestate-popstate)
15 | is required for older browsers.
16 |
17 | - You have the option to perform _server-side rendering_ later if you need to increase your app perceived performance.
18 |
19 | - You need to [configure URL rewriting](#server-configuration) on your server so that all routes serve your index file.
20 |
21 | It is still possible to revert to the hash strategy, but unless you have specific needs, you should stick with the
22 | default HTML5 routing mode.
23 |
24 | ## Server configuration
25 |
26 | To allow your angular application working properly as a _Single Page Application_ (SPA) and allow bookmarking or
27 | refreshing any page, you need some configuration on your server, otherwise you will be running into troubles.
28 |
29 | > Note that during development, the live reload server already supports SPA mode.
30 |
31 | The basic idea is simply to serve the `index.html` file for every request aimed at your application.
32 |
33 | Here is an example on how to perform this on an [Express](http://expressjs.com) NodeJS server:
34 |
35 | ```js
36 | // Put this in your `server.js` file, after your other rules (APIs, static files...)
37 | app.get('/*', function(req, res) {
38 | res.sendFile(__dirname + '/index.html');
39 | });
40 | ```
41 |
42 | For other servers like [Nginx](https://www.nginx.com/blog/creating-nginx-rewrite-rules/) or
43 | [Apache](http://httpd.apache.org/docs/2.0/misc/rewriteguide.html), you may look for how to perform _URL rewriting_.
44 |
--------------------------------------------------------------------------------
/docs/updating.md:
--------------------------------------------------------------------------------
1 | # Updating npm dependencies
2 |
3 | - Check outdated packages
4 |
5 | ```sh
6 | npm outdated
7 | ```
8 |
9 | - Update local packages according to `package.json`
10 |
11 | ```sh
12 | npm update
13 | ```
14 |
15 | - Upgrade packages manually
16 |
17 | ```sh
18 | npm install --save[-dev] @latest
19 | ```
20 |
21 | Alternatively, you can use [npm-check](https://github.com/dylang/npm-check) to perform an interactive upgrade:
22 |
23 | ```sh
24 | npm-check -u --skip-unused
25 | ```
26 |
27 | ## Locking package versions
28 |
29 | Starting from `npm@5` a new `package-lock.json` file is
30 | [automatically generated](https://docs.npmjs.com/files/package-locks) when using `npm install` commands, to ensure a
31 | reproducible dependency tree and avoid unwanted package updates.
32 |
33 | If you use a previous npm version, it is recommended to use [npm shrinkwrap](https://docs.npmjs.com/cli/shrinkwrap) to
34 | lock down all your dependencies version:
35 |
36 | ```sh
37 | npm shrinkwrap --dev
38 | ```
39 |
40 | This will create a file `npm-shrinkwrap.json` alongside your `package.json` files.
41 |
42 | > Do not forget to run shrinkwrap each time you manually update your dependencies!
43 |
44 | # Updating angular-related dependencies
45 |
46 | See the [Angular update website](https://update.angular.io) to guide you through the updating/upgrading steps.
47 |
--------------------------------------------------------------------------------
/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: ['./src/**/*.e2e-spec.ts'],
9 | capabilities: {
10 | browserName: process.env.PROTRACTOR_BROWSER || 'chrome'
11 | },
12 | // Only works with Chrome and Firefox
13 | directConnect: true,
14 | baseUrl: 'http://localhost:4200/',
15 | framework: 'jasmine2',
16 | jasmineNodeOpts: {
17 | showColors: true,
18 | defaultTimeoutInterval: 30000,
19 | print: function() {}
20 | },
21 | onPrepare() {
22 | require('ts-node').register({
23 | project: require('path').join(__dirname, './tsconfig.e2e.json')
24 | });
25 | // Better console spec reporter
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('app', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display hello message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Hello world !');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Use the Page Object pattern to define the page under test.
3 | * See docs/coding-guide/e2e-tests.md for more info.
4 | */
5 |
6 | import { browser, element, by } from 'protractor';
7 |
8 | export class AppPage {
9 | constructor() {
10 | // Forces default language
11 | this.navigateTo();
12 | if (localStorage) {
13 | browser.executeScript(() => localStorage.setItem('language', 'en-US'));
14 | }
15 | }
16 |
17 | navigateTo() {
18 | return browser.get('/');
19 | }
20 |
21 | getParagraphText() {
22 | return element(by.css('app-root mat-card-title')).getText();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/e2e",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": ["jasmine", "jasminewd2", "node"]
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/ngsw-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": "/index.html",
3 | "assetGroups": [
4 | {
5 | "name": "app",
6 | "installMode": "prefetch",
7 | "resources": {
8 | "files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"]
9 | }
10 | },
11 | {
12 | "name": "assets",
13 | "installMode": "lazy",
14 | "updateMode": "prefetch",
15 | "resources": {
16 | "files": ["/assets/**"]
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@angular-material-extension/freelancer-theme",
3 | "version": "0.0.0-development",
4 | "license": "MIT",
5 | "scripts": {
6 | "ng": "ng",
7 | "build": "npm run env -s && ng build --prod",
8 | "build:doc": "cd ../ && gulp build:doc",
9 | "build:prod": "ng build --prod ",
10 | "build:ci": "ng build --prod --build-optimizer --base-href /freelancer-theme/ --deploy-url /freelancer-theme/",
11 | "build:client-and-server-bundles": "npm run env -s && ng build --prod && ng run freelancer-theme:server:production",
12 | "build:client-and-server-bundles:ci": "npm run env -s && npm run build:ci && ng run freelancer-theme:server:production",
13 | "build:prerender": "npm run build:client-and-server-bundles && npm run webpack:server && npm run generate:prerender",
14 | "build:prerender:ci": "npm run build:client-and-server-bundles:ci && npm run webpack:server && npm run generate:prerender",
15 | "build:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
16 | "clean": "rm -rf dist",
17 | "codecov": "codecov",
18 | "compile:server": "tsc -p server.tsconfig.json",
19 | "deploy:demo": "ngh --dir dist/browser/ --message=\"chore(demo): deploy new version\"",
20 | "lint": "ng lint && stylelint \"src/**/*.scss\" --syntax scss && htmlhint \"src\" --config .htmlhintrc",
21 | "test": "npm run env -s && ng test",
22 | "test:ci": "npm run env -s && ng test --code-coverage --watch=false",
23 | "e2e": "npm run env -s && ng e2e",
24 | "translations:extract": "ngx-translate-extract --input ./src --output ./src/translations/template.json --format=json --clean -sort --marker extract",
25 | "docs": "hads ./docs -o",
26 | "env": "ngx-scripts env npm_package_version",
27 | "generate:prerender": "cd dist && node prerender",
28 | "prettier": "prettier --write \"./{src,e2e}/**/*.{ts,js,scss}\"",
29 | "prettier:check": "prettier --list-different \"./{src,e2e}/**/*.{ts,js,scss}\"",
30 | "postinstall": "npm run prettier -s",
31 | "precommit": "pretty-quick --staged",
32 | "generate": "ng generate",
33 | "semantic-release": "semantic-release",
34 | "start": "npm run env -s && ng serve --aot --proxy-config proxy.conf.js --port 4210",
35 | "serve:prod": "ng serve --prod",
36 | "serve:prerender": "cd dist/browser && http-server",
37 | "serve:ssr": "node dist/server",
38 | "serve:sw": "npm run build -s && npx http-server ./dist -p 4200",
39 | "webpack:server": "webpack --config webpack.server.config.js --progress --colors"
40 | },
41 | "dependencies": {
42 | "@angular/animations": "^7.2.8",
43 | "@angular/cdk": "^7.3.4",
44 | "@angular/common": "^7.2.8",
45 | "@angular/compiler": "^7.2.8",
46 | "@angular/core": "^7.2.8",
47 | "@angular/flex-layout": "7.0.0-beta.24",
48 | "@angular/forms": "^7.2.8",
49 | "@angular/http": "^7.2.8",
50 | "@angular/material": "^7.3.4",
51 | "@angular/platform-browser": "^7.2.8",
52 | "@angular/platform-browser-dynamic": "^7.2.8",
53 | "@angular/platform-server": "^7.2.8",
54 | "@angular/router": "^7.2.8",
55 | "@angular/service-worker": "^7.2.8",
56 | "@nguniversal/express-engine": "^7.1.1",
57 | "@nguniversal/module-map-ngfactory-loader": "^7.1.1",
58 | "@ngx-translate/core": "^11.0.1",
59 | "angulartics2": "^7.4.1",
60 | "core-js": "^2.6.9",
61 | "hammerjs": "^2.0.8",
62 | "lodash": "^4.17.14",
63 | "material-design-icons": "^3.0.1",
64 | "material-design-icons-iconfont": "^5.0.1",
65 | "ngx-webstorage": "^3.0.2",
66 | "rxjs": "^6.4.0",
67 | "ts-loader": "^5.3.3",
68 | "tslib": "^1.10.0",
69 | "zone.js": "^0.8.29"
70 | },
71 | "devDependencies": {
72 | "@angular-devkit/build-angular": "^0.13.5",
73 | "@angular/cli": "^7.3.5",
74 | "@angular/compiler-cli": "^7.2.8",
75 | "@angular/language-service": "^7.2.8",
76 | "@biesbjerg/ngx-translate-extract": "^2.3.4",
77 | "@ngx-rocket/scripts": "^3.0.4",
78 | "@semantic-release/changelog": "^3.0.4",
79 | "@semantic-release/commit-analyzer": "^6.2.0",
80 | "@semantic-release/git": "^7.0.16",
81 | "@semantic-release/release-notes-generator": "^7.2.1",
82 | "@types/express": "^4.17.0",
83 | "@types/jasmine": "^3.3.13",
84 | "@types/jasminewd2": "^2.0.2",
85 | "@types/lodash": "^4.14.136",
86 | "@types/node": "^10.14.12",
87 | "angular-cli-ghpages": "^0.5.3",
88 | "codecov": "^3.2.0",
89 | "codelyzer": "^4.4.4",
90 | "express": "^4.17.1",
91 | "hads": "^1.7.2",
92 | "htmlhint": "^0.10.3",
93 | "http-server": "^0.11.1",
94 | "https-proxy-agent": "^2.2.2",
95 | "husky": "^1.3.1",
96 | "jasmine-core": "~3.3.0",
97 | "jasmine-spec-reporter": "^4.1.0",
98 | "karma": "^4.2.0",
99 | "karma-chrome-launcher": "^2.2.0",
100 | "karma-cli": "~2.0.0",
101 | "karma-coverage-istanbul-reporter": "^2.0.5",
102 | "karma-jasmine": "^2.0.1",
103 | "karma-junit-reporter": "^1.2.0",
104 | "prettier": "^1.18.2",
105 | "pretty-quick": "^1.11.1",
106 | "protractor": "~5.4.0",
107 | "puppeteer": "^1.18.1",
108 | "reflect-metadata": "^0.1.13",
109 | "semantic-release": "^15.13.18",
110 | "stylelint": "~9.10.1",
111 | "stylelint-config-prettier": "^4.0.0",
112 | "stylelint-config-recommended-scss": "~3.2.0",
113 | "stylelint-config-standard": "~18.2.0",
114 | "stylelint-scss": "^3.9.1",
115 | "ts-node": "^8.3.0",
116 | "tslint": "~5.12.1",
117 | "tslint-config-prettier": "^1.18.0",
118 | "typescript": "~3.2.4",
119 | "webpack-cli": "^3.3.5"
120 | },
121 | "jest": {
122 | "preset": "jest-preset-angular",
123 | "coverageReporters": [
124 | "lcov",
125 | "text"
126 | ],
127 | "setupTestFrameworkScriptFile": "/src/setupJest.ts"
128 | },
129 | "prettier": {
130 | "singleQuote": true,
131 | "overrides": [
132 | {
133 | "files": "*.scss",
134 | "options": {
135 | "singleQuote": false
136 | }
137 | }
138 | ]
139 | },
140 | "repository": {
141 | "type": "git",
142 | "url": "https://github.com/angular-material-extensions/freelancer-theme.git"
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/prerender.ts:
--------------------------------------------------------------------------------
1 | // Load zone.js for the server.
2 | import 'zone.js/dist/zone-node';
3 | import 'reflect-metadata';
4 | import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
5 | import { join } from 'path';
6 |
7 | import { enableProdMode } from '@angular/core';
8 | // Faster server renders w/ Prod mode (dev mode never needed)
9 | enableProdMode();
10 |
11 | // Import module map for lazy loading
12 | import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
13 | import { renderModuleFactory } from '@angular/platform-server';
14 | import { ROUTES } from './static.paths';
15 |
16 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack
17 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main');
18 |
19 | const BROWSER_FOLDER = join(process.cwd(), 'browser');
20 |
21 | // Load the index.html file containing referances to your application bundle.
22 | const index = readFileSync(join(BROWSER_FOLDER, 'index.html'), 'utf8');
23 |
24 | let previousRender = Promise.resolve();
25 |
26 | // Iterate each route path
27 | ROUTES.forEach(route => {
28 | const fullPath = join(BROWSER_FOLDER, route);
29 |
30 | // Make sure the directory structure is there
31 | if (!existsSync(fullPath)) {
32 | mkdirSync(fullPath);
33 | }
34 |
35 | // Writes rendered HTML to index.html, replacing the file if it already exists.
36 | previousRender = previousRender
37 | .then(_ =>
38 | renderModuleFactory(AppServerModuleNgFactory, {
39 | document: index,
40 | url: route,
41 | extraProviders: [provideModuleMap(LAZY_MODULE_MAP)]
42 | })
43 | )
44 | .then(html => writeFileSync(join(fullPath, 'index.html'), html));
45 | });
46 |
--------------------------------------------------------------------------------
/proxy.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const HttpsProxyAgent = require('https-proxy-agent');
4 |
5 | /*
6 | * API proxy configuration.
7 | * This allows you to proxy HTTP request like `http.get('/api/stuff')` to another server/port.
8 | * This is especially useful during app development to avoid CORS issues while running a local server.
9 | * For more details and options, see https://github.com/angular/angular-cli#proxy-to-backend
10 | */
11 | const proxyConfig = [
12 | {
13 | context: '/api',
14 | pathRewrite: { '^/api': '' },
15 | target: 'https://api.chucknorris.io',
16 | changeOrigin: true,
17 | secure: false
18 | }
19 | ];
20 |
21 | /*
22 | * Configures a corporate proxy agent for the API proxy if needed.
23 | */
24 | function setupForCorporateProxy(proxyConfig) {
25 | if (!Array.isArray(proxyConfig)) {
26 | proxyConfig = [proxyConfig];
27 | }
28 |
29 | const proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
30 | let agent = null;
31 |
32 | if (proxyServer) {
33 | console.log(`Using corporate proxy server: ${proxyServer}`);
34 | agent = new HttpsProxyAgent(proxyServer);
35 | proxyConfig.forEach(entry => {
36 | entry.agent = agent;
37 | });
38 | }
39 |
40 | return proxyConfig;
41 | }
42 |
43 | module.exports = setupForCorporateProxy(proxyConfig);
44 |
--------------------------------------------------------------------------------
/server.ts:
--------------------------------------------------------------------------------
1 | import 'zone.js/dist/zone-node';
2 | import 'reflect-metadata';
3 | import { enableProdMode } from '@angular/core';
4 | // Express Engine
5 | import { ngExpressEngine } from '@nguniversal/express-engine';
6 | // Import module map for lazy loading
7 | import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
8 |
9 | import * as express from 'express';
10 | import { join } from 'path';
11 |
12 | // Faster server renders w/ Prod mode (dev mode never needed)
13 | enableProdMode();
14 |
15 | // Express server
16 | const app = express();
17 |
18 | const PORT = process.env.PORT || 4000;
19 | const DIST_FOLDER = join(process.cwd(), 'dist');
20 |
21 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack
22 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main');
23 |
24 | // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
25 | app.engine(
26 | 'html',
27 | ngExpressEngine({
28 | bootstrap: AppServerModuleNgFactory,
29 | providers: [provideModuleMap(LAZY_MODULE_MAP)]
30 | })
31 | );
32 |
33 | app.set('view engine', 'html');
34 | app.set('views', join(DIST_FOLDER, 'browser'));
35 |
36 | // Example Express Rest API endpoints
37 | // app.get('/api/**', (req, res) => { });
38 | // Server static files from /browser
39 | app.get(
40 | '*.*',
41 | express.static(join(DIST_FOLDER, 'browser'), {
42 | maxAge: '1y'
43 | })
44 | );
45 |
46 | // All regular routes use the Universal engine
47 | app.get('*', (req: any, res: any) => {
48 | res.render('index', { req });
49 | });
50 |
51 | // Start up the Node server
52 | app.listen(PORT, () => {
53 | console.log(`Node Express server listening on http://localhost:${PORT}`);
54 | });
55 |
--------------------------------------------------------------------------------
/src/app/about/about-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 |
4 | import { extract } from '@app/core';
5 | import { AboutComponent } from './about.component';
6 |
7 | const routes: Routes = [
8 | // Module is lazy loaded, see app-routing.module.ts
9 | { path: '', component: AboutComponent, data: { title: extract('About') } }
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forChild(routes)],
14 | exports: [RouterModule],
15 | providers: []
16 | })
17 | export class AboutRoutingModule {}
18 |
--------------------------------------------------------------------------------
/src/app/about/about.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | APP_NAME
5 |
6 |
7 | code
8 | Version {{ version }}
9 |
10 |
11 |