diff --git a/.gitignore b/.gitignore
index a87544020..294817b6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,8 +63,8 @@ libs/file-uploader/src/**/*.js
libs/file-uploader/src/**/*.js.map
libs/portfolio/src/**/*.js
libs/portfolio/src/**/*.js.map
-libs/route-pages/blog-portfolio/src/**/*.js
-libs/route-pages/blog-portfolio/src/**/*.js.map
+libs/route-pages/blog/src/**/*.js
+libs/route-pages/blog/src/**/*.js.map
libs/route-pages/careers/src/**/*.js
libs/route-pages/careers/src/**/*.js.map
libs/route-pages/for-clients/src/**/*.js
diff --git a/apps/valor-software-site/project.json b/apps/valor-software-site/project.json
index 622e9613c..8659aecd5 100644
--- a/apps/valor-software-site/project.json
+++ b/apps/valor-software-site/project.json
@@ -121,6 +121,6 @@
"route-pages-services-page",
"route-pages-careers",
"route-pages-for-clients",
- "route-pages-blog-portfolio"
+ "route-pages-blog"
]
}
diff --git a/apps/valor-software-site/src/app/app.routing.ts b/apps/valor-software-site/src/app/app.routing.ts
index 2b9779f54..2eae160f6 100644
--- a/apps/valor-software-site/src/app/app.routing.ts
+++ b/apps/valor-software-site/src/app/app.routing.ts
@@ -29,11 +29,11 @@ export const routes: Routes = [
},
{
path: 'articles',
- loadChildren: () => import('@valor-software/blog-portfolio').then(m => m.BlogPortfolioModule)
+ loadChildren: () => import('@valor-software/blog').then(m => m.BlogModule)
},
{
path: 'projects',
- loadChildren: () => import('@valor-software/blog-portfolio').then(m => m.BlogPortfolioModule)
+ loadChildren: () => import('@valor-software/projects').then(m => m.ProjectsModule)
},
{
path: 'privacy-policy',
diff --git a/libs/common-docs/src/common-docs.module.ts b/libs/common-docs/src/common-docs.module.ts
index 2700d2a16..8b7728da8 100644
--- a/libs/common-docs/src/common-docs.module.ts
+++ b/libs/common-docs/src/common-docs.module.ts
@@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common';
import { PopoverComponent } from './components/popover/popover.component';
import { TopMenuComponent } from './components/top-menu/top-menu.component';
import { RouterModule } from '@angular/router';
-import { ImgHoverDirective } from './directives/img-hover.directive';
import { ContactModalComponent } from './components/contact-modal/contact-modal.components';
import { ModalService } from './services/modal.service';
import { ReactiveFormsModule } from '@angular/forms';
@@ -14,7 +13,7 @@ import { ResultModalComponent } from './components/result-modal/result-modal.com
import { AppFooterComponent } from './components/app-footer/app-footer.component';
import { ServicesBlockComponent } from './components/services_block/services-block.component';
import { BreadCrumbsComponent } from './components/breadCrumbs/breadCrumbs.component';
-import { ShowHideDirective } from './directives/showHide.directive';
+import { ShowHideDirective, ImgHoverDirective, SortDirective } from './directives';
import { SwiperModule } from 'swiper/angular';
import { BlogPreviewComponent } from './components/blog-preview/blog-preview.component';
import { BlogPortfolioItemComponent } from './components/blog-preview/blog-portfolio-item.component';
@@ -34,13 +33,12 @@ import { CookieConsentBannerComponent } from './components/cookie-consent-banner
export { PopoverComponent } from './components/popover/popover.component';
export { TopMenuComponent } from './components/top-menu/top-menu.component';
-export { ImgHoverDirective } from './directives/img-hover.directive';
+export { ShowHideDirective, ImgHoverDirective, SortDirective } from './directives';
export { AppFooterComponent } from './components/app-footer/app-footer.component';
export { ServicesBlockComponent } from './components/services_block/services-block.component';
export { ContactModalComponent } from './components/contact-modal/contact-modal.components';
export { ModalService } from './services/modal.service';
export { BreadCrumbsComponent } from './components/breadCrumbs/breadCrumbs.component';
-export { ShowHideDirective } from './directives/showHide.directive';
export { GetArticlesService } from './services/getArticles.service';
export { IArticle } from './models/article.interface';
export { BlogPreviewComponent } from './components/blog-preview/blog-preview.component';
@@ -87,7 +85,8 @@ export { CookieConsentBannerComponent } from './components/cookie-consent-banner
ChallengeCardComponent,
TechnologiesCardComponent,
TechnologiesComponent,
- CookieConsentBannerComponent
+ CookieConsentBannerComponent,
+ SortDirective
],
imports: [
CommonModule,
@@ -116,7 +115,8 @@ export { CookieConsentBannerComponent } from './components/cookie-consent-banner
ChallengeCardComponent,
TechnologiesCardComponent,
TechnologiesComponent,
- CookieConsentBannerComponent
+ CookieConsentBannerComponent,
+ SortDirective
],
providers: [
ModalService,
diff --git a/libs/common-docs/src/components/blog-preview/blog-portfolio-item.component.ts b/libs/common-docs/src/components/blog-preview/blog-portfolio-item.component.ts
index 4bdae7002..89e60e7a6 100644
--- a/libs/common-docs/src/components/blog-preview/blog-portfolio-item.component.ts
+++ b/libs/common-docs/src/components/blog-preview/blog-portfolio-item.component.ts
@@ -7,7 +7,7 @@ import { IPortfolio } from "../../models/portfolio.interface";
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'blog-portfolio-item',
template:`
-
+
= new EventEmitter();
+
+ @Output() changedArticles: EventEmitter
= new EventEmitter();
+
+ sortProjectItems(value: string[]) {
+ if (!value.length || value.includes('all_projects')) {
+ this.changedProjects.emit(this.projects);
+ return;
+ }
+
+ const files = new Set();
+
+ value.map(val => {
+ let filterRes: IPortfolio[] | undefined = [];
+ filterRes = this.projects?.filter((item: IPortfolio) => item.sortServices.includes(val));
+ if (filterRes?.length) {
+ filterRes.map(item => files.add(item));
+ }
+ });
+ this.changedProjects.emit([...files]);
+ }
+
+
+ sortArticleItems(value: string[]) {
+ if (!value.length) {
+ this.changedArticles.emit(this._items);
+ return;
+ }
+
+ const files = new Set();
+ const lang = value.includes('pt') ? 'pt' : 'en';
+ const langFiles: IArticle[] | undefined = this._items?.filter((item: IArticle) => item.language === lang);
+ if (value.length === 1 && langFiles?.length) {
+ langFiles.map(item => files.add(item));
+ this.changedArticles.emit([...files]);
+ return;
+ }
+
+ value.map(val => {
+ let filterRes: IArticle[] | undefined = [];
+ filterRes = langFiles?.filter((item: IArticle) => item.domains.includes(val));
+ if (filterRes?.length) {
+ filterRes.map(item => files.add(item));
+ }
+ });
+ this.changedArticles.emit([...files]);
+ }
+}
diff --git a/libs/common-docs/src/directives/index.ts b/libs/common-docs/src/directives/index.ts
new file mode 100644
index 000000000..f242d203b
--- /dev/null
+++ b/libs/common-docs/src/directives/index.ts
@@ -0,0 +1,4 @@
+export * from './blog-portfolio/sort.directive';
+export * from './collapse-animations';
+export * from './img-hover.directive';
+export * from './showHide.directive';
\ No newline at end of file
diff --git a/libs/common-docs/src/models/index.ts b/libs/common-docs/src/models/index.ts
new file mode 100644
index 000000000..8e81a0af5
--- /dev/null
+++ b/libs/common-docs/src/models/index.ts
@@ -0,0 +1,3 @@
+export * from './article.interface';
+export * from './popover.interface';
+export * from './portfolio.interface';
\ No newline at end of file
diff --git a/libs/common-docs/src/models/popover.model.ts b/libs/common-docs/src/models/popover.interface.ts
similarity index 100%
rename from libs/common-docs/src/models/popover.model.ts
rename to libs/common-docs/src/models/popover.interface.ts
diff --git a/libs/route-pages/blog-portfolio/README.md b/libs/route-pages/blog-portfolio/README.md
deleted file mode 100644
index a18e0eb6e..000000000
--- a/libs/route-pages/blog-portfolio/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# route-pages-blog-portfolio
-
-This library was generated with [Nx](https://nx.dev).
-
-
-## Running unit tests
-
-Run `nx test route-pages-blog-portfolio` to execute the unit tests.
-
diff --git a/libs/route-pages/blog-portfolio/project.json b/libs/route-pages/blog-portfolio/project.json
deleted file mode 100644
index cac23bd74..000000000
--- a/libs/route-pages/blog-portfolio/project.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "route-pages-blog-portfolio",
- "$schema": "../../../node_modules/nx/schemas/project-schema.json",
- "projectType": "library",
- "sourceRoot": "libs/route-pages/blog-portfolio/src",
- "prefix": "valor-software-site-base",
- "targets": {
- "build": {
- "executor": "@nx/angular:ng-packagr-lite",
- "outputs": ["dist/libs/route-pages/blog-portfolio"],
- "options": {
- "project": "libs/route-pages/blog-portfolio/ng-package.json"
- },
- "configurations": {
- "production": {
- "tsConfig": "libs/route-pages/blog-portfolio/tsconfig.lib.prod.json"
- },
- "development": {
- "tsConfig": "libs/route-pages/blog-portfolio/tsconfig.lib.json"
- }
- },
- "defaultConfiguration": "production"
- },
- "test": {
- "executor": "@nx/jest:jest",
- "outputs": ["coverage/libs/route-pages/blog-portfolio"],
- "options": {
- "jestConfig": "libs/route-pages/blog-portfolio/jest.config.ts",
- "passWithNoTests": true
- }
- },
- "lint": {
- "executor": "@nx/linter:eslint",
- "options": {
- "lintFilePatterns": [
- "libs/route-pages/blog-portfolio/src/**/*.ts",
- "libs/route-pages/blog-portfolio/src/**/*.html"
- ]
- }
- }
- },
- "tags": [],
- "implicitDependencies": ["common-docs", "feedback"]
-}
diff --git a/libs/route-pages/blog-portfolio/src/article.component.ts b/libs/route-pages/blog-portfolio/src/article.component.ts
deleted file mode 100644
index 2aef71335..000000000
--- a/libs/route-pages/blog-portfolio/src/article.component.ts
+++ /dev/null
@@ -1,220 +0,0 @@
-import { Component, Inject, OnDestroy } from '@angular/core';
-import { DomSanitizer } from '@angular/platform-browser';
-import { NavigationEnd, Router } from "@angular/router";
-import { checkHTMLExtension, GetArticlesService, IArticle, OLD_ROUTES_FROM_OLD_SITE } from "@valor-software/common-docs";
-import { filter, switchMap, catchError } from 'rxjs/operators';
-import { Subscription, of } from "rxjs";
-
-@Component({
- // eslint-disable-next-line @angular-eslint/component-selector
- selector: 'article',
- styles: [`
- ::ng-deep.turbo-table {
- margin-top: 25px;
- }
- ::ng-deep.turbo-table tbody tr:not(:first-of-type) {
- border-top: 1px solid gray;
- }
- ::ng-deep.turbo-table tbody tr:not(:first-of-type) td:not(:last-of-type){
- border-right: 1px solid gray
- }
- ::ng-deep.turbo-table tbody tr:not(:first-of-type) td{
- padding: 5px 10px;
- }
- ::ng-deep tbody tr:first-of-type {
- text-align: center;
- }
- ::ng-deep mark{
- background-color: #A9A9A9;
- color: #383838;
- border-radius: 0.3em;
- padding: 0.1em 0.25em;
- }
- ::ng-deep.white{
- color: #ffffff;
- }
- ::ng-deep.small-img {
- margin: auto;
- width: 40%
- }
- ::ng-deep.block-citation {
- border-left-width: 8px;
- --tw-border-opacity: 1;
- border-color: rgba(32, 32, 32, var(--tw-border-opacity));
- --tw-bg-opacity: 1;
- background-color: #2c2c2d;
- }
- ::ng-deep.block-citation>.attribution {
- padding: 0 16px 16px 16px;
- text-align: right;
- }
- ::ng-deep.block-citation>blockquote {
- border: 0px;
- border-radius: 3rem;
- }
- ::ng-deep.block-citation>blockquote>.paragraph:first-of-type:before {
- content: open-quote;
- float: left;
- font-size: 3em;
- margin-right: 4px;
- font-weight: 700;
- line-height: 0.6em;
- color: rgba(226, 78, 99, var(--tw-text-opacity));
- }
- ::ng-deep.block-citation>blockquote>.paragraph:first-of-type:after {
- content: no-close-quote;
- }
-
- `],
- templateUrl: './article.component.html'
-})
-export class ArticleComponent implements OnDestroy {
- changeBreadCrumbTitle?: { path: string, title: string }[];
- article?: IArticle;
- $routEvents?: Subscription;
- linksFromOldSite?: { [key: string]: string };
-
- constructor(
- private router: Router,
- private getArticleServ: GetArticlesService,
- private sanitizer: DomSanitizer,
- @Inject(OLD_ROUTES_FROM_OLD_SITE) linkList: { [key: string]: string },
- ) {
- this.linksFromOldSite = linkList;
- this.$routEvents = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event) => {
- this.checkRoutePath();
- });
-
- if (!this.article) {
- this.checkRoutePath();
- }
- }
-
- checkRoutePath() {
- let artTitle = this.router.parseUrl(this.router.url).root.children.primary.segments[1].path;
- if (!artTitle) {
- this.router.navigate(['404']);
- }
-
- if (artTitle) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- artTitle = this.linksFromOldSite[artTitle] ? this.linksFromOldSite[artTitle] : artTitle;
- artTitle = checkHTMLExtension(artTitle);
- this.getArticleServ.getArticleRequest(artTitle).pipe(
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- switchMap((art) => {
- this.article = art;
- this.changeBreadCrumbTitle = [{
- path: this.router.parseUrl(this.router.url).root.children.primary.segments[1].path,
- title: art.title
- }];
- return this.getArticleServ.getHTMLSource(artTitle);
- }),
- catchError(error => {
- if (!this.article) {
- this.router.navigate(['404']);
- }
- return of();
- })
- ).subscribe(res => {
- if (this.article) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- this.article.content = res;
- this.addScriptsToHead();
- }
- }, error => {
- this.router.navigate(['404']);
- });
- }
- }
-
- checkHTML(html: string) {
- return this.sanitizer.bypassSecurityTrustHtml(html);
- }
-
- routLink(event: any) {
- const element = event.target;
-
- if (element.nodeName === 'A' && element.getAttribute('routerLink')) {
- event.preventDefault();
- const link = element.getAttribute('routerLink');
- this.router.navigate([link]);
- }
-
- if (element.nodeName === 'A' && element.getAttribute('href')) {
- const link = element.getAttribute('href');
- if (link.includes('#')) {
- event.preventDefault();
- let url = this.router.url;
- if (url.indexOf('#') > -1) {
- url = url.substring(0, url.indexOf('#'));
- }
-
- if (url.indexOf('%23') > -1) {
- url = url.substring(0, url.indexOf('%23'));
- }
-
- if (link) {
- this.router.navigate([url.trim() + '/'], { fragment: link.replace('#', '') });
- }
- }
- }
- }
-
- ngOnDestroy() {
- this.$routEvents?.unsubscribe();
- this.removeOldMicroDAta();
- }
-
- addScriptsToHead() {
- this.removeOldMicroDAta();
- const head = document.getElementsByTagName('head')[0];
- const script = document.createElement('script');
- script.setAttribute('id', 'article-micro-data');
- script.setAttribute('type', 'application/ld+json');
- script.innerHTML = `
- {
- "@context": "https://schema.org/",
- "@type": "BlogPosting",
- "mainEntityOfPage": {
- "@type": "WebPage",
- "@id": "https://valor-software.com${this.router.url}"
- },
- "headline": "${this.article?.title}",
- "description": "${this.article?.seoDescription}",
- "image": {
- "@type": "ImageObject",
- "url": "https://valor-software.com/${this.article?.bgImg}",
- "width": "",
- "height": ""
- },
- "author": {
- "@type": "Organization",
- "name": "${this.article?.author}"
- },
- "publisher": {
- "@type": "Organization",
- "name": "Valor Software",
- "logo": {
- "@type": "ImageObject",
- "url": "https://valor-software.com/assets/img/valor_img/valor-logo.svg",
- "width": "",
- "height": ""
- }
- },
- "datePublished": "${this.article?.date}"
- }
- `;
- head.insertBefore(script, head.firstChild);
- }
-
- removeOldMicroDAta() {
- const oldMicroDAta = document.getElementById('article-micro-data');
- if (oldMicroDAta) {
- oldMicroDAta.remove();
- }
- }
-}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/blog-portfolio.module.ts b/libs/route-pages/blog-portfolio/src/blog-portfolio.module.ts
deleted file mode 100644
index ba569cb38..000000000
--- a/libs/route-pages/blog-portfolio/src/blog-portfolio.module.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { RouterModule } from "@angular/router";
-import { routes } from './routes';
-import { GeneralPageComponent } from "./general-page.component";
-import { CommonDocsModule } from "@valor-software/common-docs";
-import { BlogComponent } from "./blog.component";
-import { ProjectsBlockComponent } from "./projects-block.component";
-import { SortDirective } from './directives/sort.directive';
-import { GeneralItemComponent } from './general-item.component';
-import { ArticleComponent } from './article.component';
-import { ProjectComponent } from './project.component';
-import { FeedbackModule } from "@valor-software/feedback";
-import { SwiperModule } from "swiper/angular";
-
-@NgModule({
- declarations: [
- GeneralPageComponent,
- BlogComponent,
- ProjectsBlockComponent,
- SortDirective,
- GeneralItemComponent,
- ArticleComponent,
- ProjectComponent
- ],
- imports: [
- CommonModule,
- RouterModule.forChild(routes),
- CommonDocsModule,
- FeedbackModule,
- SwiperModule
- ]
-})
-export class BlogPortfolioModule { }
-
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/blog.component.ts b/libs/route-pages/blog-portfolio/src/blog.component.ts
deleted file mode 100644
index 5e757fcfb..000000000
--- a/libs/route-pages/blog-portfolio/src/blog.component.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { AfterViewInit, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core';
-import { GetArticlesService, titleRefactoring } from "@valor-software/common-docs";
-import { Subscription } from "rxjs";
-import { IArticle } from "@valor-software/common-docs";
-import { Router } from "@angular/router";
-
-export const Domains = {
- business_analysis: 'Business Analysis',
- user_research_design: 'User Research & Design',
- dev_quality_assurance: 'Development & Quality Assurance',
- devops_cloud: 'DevOps & Cloud',
- recruitment_pm: 'Recruitment & Project Mgmt.',
- sales_marketing: 'Sales & Marketing',
- module_federation: 'Module Federation',
- other: 'Other'
-};
-
-export const Languages = {
- en: 'English',
- pt: 'Portuguese'
-};
-
-@Component({
- // eslint-disable-next-line @angular-eslint/component-selector
- selector: 'blog-block',
- templateUrl: './blog.component.html'
-})
-export class BlogComponent implements OnDestroy, AfterViewInit {
- sortList: string[] = [];
- sortLang: string[] = [];
- $articles?: Subscription;
- articles?: IArticle[];
- sortArticles?: IArticle[] = [];
- activeIndex: string[] = [];
- showAll = false;
- isCollapsed = true;
-
- @Input() set _articles(value: IArticle[]) {
- this.articles = Object.assign(value);
- this.sortArticles = Object.assign(value);
- }
-
- constructor(
- private router: Router,
- private getArticles: GetArticlesService,
- private cdr: ChangeDetectorRef,
- ) {
- this.getSortKeys();
- }
-
- ngAfterViewInit(): void {
- this.toggleLanguage('en');
- }
-
- getSortKeys() {
- const sortSet = new Set();
- Object.keys(Domains).map(key => sortSet.add(key));
- this.sortList = [...sortSet];
-
- const sortLang = new Set();
- Object.keys(Languages).map(key => sortLang.add(key));
- this.sortLang = [...sortLang];
- }
-
- getDomainTitle(key: string) {
- const resKey = key as keyof typeof Domains;
- return Domains[resKey];
- }
-
- getLanguageTitle(key: string) {
- const resKey = key as keyof typeof Languages;
- return Languages[resKey];
- }
-
- toggleActiveIndex(key: string) {
- if (this.activeIndex.includes(key)) {
- this.activeIndex = this.activeIndex.filter(item => item !== key);
- this.showAll = false;
- return;
- }
-
- this.activeIndex = [...this.activeIndex, key];
- this.showAll = false;
- }
-
- toggleLanguage(key: string) {
- if (!this.activeIndex.includes(key)) {
- const keys = this.activeIndex.filter(item => item !== 'pt' && item !== 'en');
- this.activeIndex = [...keys, key];
- }
-
- this.showAll = false;
- }
-
- updateArticles(articles: IArticle[] | []) {
- this.sortArticles = articles;
- this.cdr.detectChanges();
- }
-
- resetAll() {
- const lang = this.activeIndex.includes('pt') ? 'pt' : 'en';
- this.activeIndex = [lang];
- }
-
- getRouteLink(link: string): any {
- return titleRefactoring(link);
- }
-
- checkLength(): boolean {
- return !!(this.sortArticles?.length && this.sortArticles?.length > 8);
- }
-
- ngOnDestroy() {
- this.$articles?.unsubscribe();
- }
-}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/general-item.component.ts b/libs/route-pages/blog-portfolio/src/general-item.component.ts
deleted file mode 100644
index 0c538d317..000000000
--- a/libs/route-pages/blog-portfolio/src/general-item.component.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Component, OnDestroy } from '@angular/core';
-import { NavigationEnd, Router } from "@angular/router";
-import { filter } from "rxjs/operators";
-import { Subscription } from "rxjs";
-
-const generalPaths = {
- BLOG: 'articles',
- PORTFOLIO: 'projects'
-};
-
-
-@Component({
- // eslint-disable-next-line @angular-eslint/component-selector
- selector: 'general-item',
- template: `
-
-
-
-
-
-
- `
-})
-export class GeneralItemComponent implements OnDestroy {
- $routerEvents: Subscription;
- routeUrl?: string;
-
- constructor(
- private router: Router,
- ) {
- this.$routerEvents = this.router.events
- .pipe(
- filter(event => event instanceof NavigationEnd)
- )
- .subscribe(event => {
- this.routeUrl = this.router.parseUrl(this.router.url).root.children["primary"].segments[0].path;
- });
- }
-
- isBlogPage() {
- return this.routeUrl === generalPaths.BLOG;
- }
-
- ngOnDestroy() {
- if (this.$routerEvents) {
- this.$routerEvents.unsubscribe();
- }
- }
-
-}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/general-page.component.html b/libs/route-pages/blog-portfolio/src/general-page.component.html
deleted file mode 100644
index 887c3e756..000000000
--- a/libs/route-pages/blog-portfolio/src/general-page.component.html
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
-
-
-
- {{activeProject?.name | customSlice: 40}}
- {{activeArticle?.title | customSlice: 40}}
-
-
- {{activeProject?.description | customSlice: 300}}
- {{activeArticle?.seoDescription | customSlice: 300}}
-
-
-
-
-
-
-
-
-
-
-
- {{!isBlogPage() ? 'Recent projects' : 'Latest Articles'}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{isBlogPage() ? 'Articles' : 'Projects'}}
-
-
-
-
-
-
-
diff --git a/libs/route-pages/blog-portfolio/src/index.ts b/libs/route-pages/blog-portfolio/src/index.ts
deleted file mode 100644
index 17de08f97..000000000
--- a/libs/route-pages/blog-portfolio/src/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
- export * from './blog-portfolio.module';
-
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/project.component.ts b/libs/route-pages/blog-portfolio/src/project.component.ts
deleted file mode 100644
index 5696aece5..000000000
--- a/libs/route-pages/blog-portfolio/src/project.component.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
-import { Subscription } from "rxjs";
-import { NavigationEnd, Router } from "@angular/router";
-import { filter } from "rxjs/operators";
-import { IPortfolio, GetPortfolioService, UtilService } from "@valor-software/common-docs";
-import { checkHTMLExtension, titleRefactoring } from "@valor-software/common-docs";
-
-@Component({
- // eslint-disable-next-line @angular-eslint/component-selector
- selector: 'project',
- templateUrl: 'project.component.html'
-})
-export class ProjectComponent implements OnDestroy {
- changeBreadCrumbTitle?: { path: string, title: string }[];
- project?: IPortfolio;
- $routEvents?: Subscription;
-
- constructor(
- public utilService: UtilService,
- private router: Router,
- private getProjectsServ: GetPortfolioService,
- private cdr: ChangeDetectorRef
- ) {
- this.$routEvents = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event) => {
- this.checkRoutePath();
- });
-
- if (!this.project) {
- this.checkRoutePath();
- }
- }
-
- checkRoutePath() {
- let artTitle = this.router.parseUrl(this.router.url).root.children.primary.segments[1].path;
- if (!artTitle) {
- this.router.navigate(['/404']);
- }
-
- artTitle = checkHTMLExtension(artTitle);
- this.getProjectsServ.getPortfolioRequest(artTitle).subscribe((res: IPortfolio) => {
- this.changeBreadCrumbTitle = [{
- path: this.router.parseUrl(this.router.url).root.children.primary.segments[1].path,
- title: res.name
- }];
- this.project = res;
- }, error => {
- console.log('error', error);
- this.router.navigate(['/404']);
- });
- }
-
- getRouteLink(link: string): string {
- return titleRefactoring(link);
- }
-
- getRespSrc(link: string): string {
- const arr = link.split('.');
- return `${arr[0]}_resp.${arr[1]}`;
- }
-
- changeSrc(event: Event, link: string) {
- (event.target as HTMLImageElement).src = link;
- this.cdr.detectChanges();
- }
-
- checkLength(arr: Array, number: number): boolean {
- return arr?.length > number;
- }
-
- ngOnDestroy() {
- this.$routEvents?.unsubscribe();
- }
-}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/projects-block.component.ts b/libs/route-pages/blog-portfolio/src/projects-block.component.ts
deleted file mode 100644
index d0343653d..000000000
--- a/libs/route-pages/blog-portfolio/src/projects-block.component.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import {ChangeDetectorRef, Component, Input } from '@angular/core';
-import { Router } from "@angular/router";
-import {IPortfolio, titleRefactoring} from '@valor-software/common-docs';
-
-const SortList = {
- all_projects: 'All Projects',
- web: 'Web',
- mobile: 'Mobile',
- ui: 'UI/UX',
- migration: 'Migration',
- art_intel: 'Artificial Intelligence'
-};
-
-@Component({
- // eslint-disable-next-line @angular-eslint/component-selector
- selector: 'projects-block',
- templateUrl: './projects-block.component.html'
-})
-export class ProjectsBlockComponent {
- sortList?: string[];
- projects?: IPortfolio[];
- sortProjects?: IPortfolio[] = [];
- activeIndex: string[] = ['all_projects'];
- showAll = false;
-
- @Input() set _projects (value: IPortfolio[]) {
- this.projects = Object.assign(value);
- this.updateProjects(value);
- }
-
- constructor(
- private router: Router,
- private cdr: ChangeDetectorRef,
- ) {
- this.getSortKeys();
- }
-
- getSortKeys() {
- const sortSet = new Set();
- Object.keys(SortList).map(key => sortSet.add(key));
- this.sortList = [...sortSet];
- }
-
- getSortTitle(key: string) {
- const resKey = key as keyof typeof SortList;
- return SortList[resKey];
- }
-
- toggleActiveIndex(key: string) {
- if (this.activeIndex.includes(key)) {
- this.activeIndex = this.activeIndex.filter(item => item !== key);
- if (!this.activeIndex.length) {
- this.resetAll();
- }
-
- this.showAll = false;
- return;
- }
-
- if (key) {
- this.activeIndex = this.activeIndex.filter(item => item !== 'all_projects');
- }
-
- this.activeIndex = [...this.activeIndex, key];
- this.showAll = false;
- }
-
- resetAll() {
- this.activeIndex = ['all_projects'];
- }
-
- checkLength(): boolean {
- return !!(this.sortProjects?.length && this.sortProjects?.length > 8);
- }
-
- getRouteLink(link: string): any {
- return titleRefactoring(link);
- }
-
- updateProjects(projects: IPortfolio[]) {
- if (projects) {
- this.sortProjects = Object.assign(projects);
- this.cdr.detectChanges();
- }
- }
-}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/routes.ts b/libs/route-pages/blog-portfolio/src/routes.ts
deleted file mode 100644
index 30c74a5c7..000000000
--- a/libs/route-pages/blog-portfolio/src/routes.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { GeneralPageComponent } from "./general-page.component";
-import { GeneralItemComponent } from "./general-item.component";
-import { Routes } from "@angular/router";
-
-
-export const routes: Routes = [
- {
- path: '',
- children: [
- {
- path: '',
- pathMatch: 'full',
- component: GeneralPageComponent
- },
- {
- path: 'booking',
- loadChildren: () => import('@valor-software/booking-page').then(m => m.BookingPageModule)
- },
- {
- path: 'terminus',
- loadChildren: () => import('@valor-software/terminus-page').then(m => m.TerminusPageModule)
- },
- {
- path: 'ashes-of-creation',
- loadChildren: () => import('@valor-software/ashes-page').then(m => m.AshesPageModule)
- },
- {
- path: 'dollar-street',
- loadChildren: () => import('@valor-software/dollar-street-page').then(m => m.DollarStreetPageModule)
- },
- {
- path: 'tablesready',
- loadChildren: () => import('@valor-software/tablesready-page').then(m => m.TablesReadyPageModule)
- },
- {
- path: 'liberty-flights',
- loadChildren: () => import('@valor-software/liberty-flights-page').then(m => m.LibertyFlightsPageModule)
- },
- {
- path: 'breethe',
- loadChildren: () => import('@valor-software/breethe-page').then(m => m.BreethePageModule)
- },
- {
- path: ':id',
- component: GeneralItemComponent
- }
- ]
- }
-];
-
diff --git a/libs/route-pages/blog-portfolio/src/test-setup.ts b/libs/route-pages/blog-portfolio/src/test-setup.ts
deleted file mode 100644
index e2365388c..000000000
--- a/libs/route-pages/blog-portfolio/src/test-setup.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'jest-preset-angular/setup-jest';
-
- import { getTestBed } from '@angular/core/testing';
- import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
-
- getTestBed().resetTestEnvironment();
- getTestBed().initTestEnvironment(
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting(),
- { teardown: { destroyAfterEach: false } },
- );
-
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/.eslintrc.json b/libs/route-pages/blog/.eslintrc.json
similarity index 100%
rename from libs/route-pages/blog-portfolio/.eslintrc.json
rename to libs/route-pages/blog/.eslintrc.json
diff --git a/libs/route-pages/blog-portfolio/ng-package.json b/libs/route-pages/blog/ng-package.json
similarity index 67%
rename from libs/route-pages/blog-portfolio/ng-package.json
rename to libs/route-pages/blog/ng-package.json
index 46a9a56e4..d5ff4002a 100644
--- a/libs/route-pages/blog-portfolio/ng-package.json
+++ b/libs/route-pages/blog/ng-package.json
@@ -1,6 +1,6 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
- "dest": "../../../dist/libs/route-pages/blog-portfolio",
+ "dest": "../../../dist/libs/route-pages/blog",
"lib": {
"entryFile": "src/index.ts"
}
diff --git a/libs/route-pages/blog-portfolio/package.json b/libs/route-pages/blog/package.json
similarity index 79%
rename from libs/route-pages/blog-portfolio/package.json
rename to libs/route-pages/blog/package.json
index e9719b3ac..5a1691e26 100644
--- a/libs/route-pages/blog-portfolio/package.json
+++ b/libs/route-pages/blog/package.json
@@ -1,5 +1,5 @@
{
- "name": "@valor-software/blog-portfolio",
+ "name": "@valor-software/blog",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^12.2.0",
diff --git a/libs/route-pages/blog/project.json b/libs/route-pages/blog/project.json
new file mode 100644
index 000000000..9f21f4694
--- /dev/null
+++ b/libs/route-pages/blog/project.json
@@ -0,0 +1,51 @@
+{
+ "name": "route-pages-blog",
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "library",
+ "sourceRoot": "libs/route-pages/blog/src",
+ "prefix": "valor-software-site-base",
+ "targets": {
+ "build": {
+ "executor": "@nx/angular:ng-packagr-lite",
+ "outputs": [
+ "dist/libs/route-pages/blog"
+ ],
+ "options": {
+ "project": "libs/route-pages/blog/ng-package.json"
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "libs/route-pages/blog/tsconfig.lib.prod.json"
+ },
+ "development": {
+ "tsConfig": "libs/route-pages/blog/tsconfig.lib.json"
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "test": {
+ "executor": "@nx/jest:jest",
+ "outputs": [
+ "coverage/libs/route-pages/blog"
+ ],
+ "options": {
+ "jestConfig": "libs/route-pages/blog/jest.config.ts",
+ "passWithNoTests": true
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "options": {
+ "lintFilePatterns": [
+ "libs/route-pages/blog/src/**/*.ts",
+ "libs/route-pages/blog/src/**/*.html"
+ ]
+ }
+ }
+ },
+ "tags": [],
+ "implicitDependencies": [
+ "common-docs",
+ "feedback"
+ ]
+}
diff --git a/libs/route-pages/blog/src/blog-page.component.html b/libs/route-pages/blog/src/blog-page.component.html
new file mode 100644
index 000000000..e66e0a9fd
--- /dev/null
+++ b/libs/route-pages/blog/src/blog-page.component.html
@@ -0,0 +1,80 @@
+
+ 0 && activeArticle">
+
+
+
+
+ {{activeArticle?.title | customSlice: 40}}
+
+
+ {{activeArticle?.seoDescription | customSlice: 300}}
+
+
+
+
+
+
Latest Articles
+
+
+
+
+
+
+
+
+ Articles
+ 0"
+ class="container pb-5 flex justify-between items-center md:pt-8 lg:pt-16"
+ style="max-height: 100%;">
+
+
+
+
+
diff --git a/libs/route-pages/blog-portfolio/src/general-page.component.ts b/libs/route-pages/blog/src/blog-page.component.ts
similarity index 56%
rename from libs/route-pages/blog-portfolio/src/general-page.component.ts
rename to libs/route-pages/blog/src/blog-page.component.ts
index 8c8e9011b..4d939307b 100644
--- a/libs/route-pages/blog-portfolio/src/general-page.component.ts
+++ b/libs/route-pages/blog/src/blog-page.component.ts
@@ -1,37 +1,23 @@
-import { Component, OnDestroy, Type } from '@angular/core';
+import { Component, OnDestroy } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { forkJoin, Subscription } from 'rxjs';
-import {
- GetArticlesService,
- IArticle,
- GetPortfolioService,
- IPortfolio,
- titleRefactoring
-} from '@valor-software/common-docs';
+import { GetArticlesService, IArticle, titleRefactoring } from '@valor-software/common-docs';
import SwiperCore, { Pagination, SwiperOptions } from 'swiper';
SwiperCore.use([Pagination]);
-const generalPaths = {
- BLOG: 'articles',
- PORTFOLIO: 'projects'
-};
-
@Component({
// eslint-disable-next-line @angular-eslint/component-selector
- selector: 'general-page',
- templateUrl: './general-page.component.html'
+ selector: 'blog-page',
+ templateUrl: './blog-page.component.html'
})
-export class GeneralPageComponent implements OnDestroy {
+export class BlogPageComponent implements OnDestroy {
routeUrl = '';
$generalSubscription = new Subscription();
- articles?: IArticle[];
- firstArticles?: IArticle[];
- firstProjects?: IPortfolio[];
- projects?: IPortfolio[];
+ articles: IArticle[] = [];
+ firstArticles: IArticle[] = [];
activeArticle?: IArticle;
- activeProject?: IPortfolio;
swiperConfig: SwiperOptions = {
slidesPerView: 1,
@@ -46,24 +32,16 @@ export class GeneralPageComponent implements OnDestroy {
constructor(
private readonly router: Router,
private readonly getArticlesServ: GetArticlesService,
- private readonly getPortfolio: GetPortfolioService,
) {
this.$generalSubscription.add(
this.router.events.pipe(
filter(event => event instanceof NavigationEnd)
).subscribe(event => {
this.routeUrl = this.router.parseUrl(this.router.url).root.children['primary']?.segments[0].path;
-
- this.isBlogPage()
- ? this._initObserveFullListOfArticles()
- : this._initObserveFullListOfPortfolio();
+ this._initObserveFullListOfArticles();
}));
}
- isBlogPage() {
- return this.routeUrl === generalPaths.BLOG;
- }
-
getFirstProjects(value: Type[]): Type[] {
return value.slice(0, 4);
}
@@ -76,31 +54,12 @@ export class GeneralPageComponent implements OnDestroy {
if (this.activeArticle) {
this.firstArticles = this.firstArticles?.filter(item => item !== this.activeArticle);
}
-
- if (this.activeProject) {
- this.firstProjects = this.firstProjects?.filter(item => item !== this.activeProject);
- }
}
ngOnDestroy() {
this.$generalSubscription.unsubscribe();
}
- private _initObserveFullListOfPortfolio() {
- this.$generalSubscription.add(
- forkJoin(
- this.getPortfolio.getFullListOfPortfolio()
- ).subscribe((res?: IPortfolio[]) => {
- if (res) {
- this.projects = Object.assign(res);
- this.firstProjects = this.getFirstProjects(res);
- this.activeProject = this.firstProjects[0];
- this.filterFirstItems();
- }
- })
- );
- }
-
private _initObserveFullListOfArticles() {
this.$generalSubscription.add(
forkJoin(
diff --git a/libs/route-pages/blog/src/blog.module.ts b/libs/route-pages/blog/src/blog.module.ts
new file mode 100644
index 000000000..78a5b9545
--- /dev/null
+++ b/libs/route-pages/blog/src/blog.module.ts
@@ -0,0 +1,27 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { RouterModule } from '@angular/router';
+import { routes } from './routes';
+import { BlogPageComponent } from './blog-page.component';
+import { CommonDocsModule } from '@valor-software/common-docs';
+import { BlogComponent, ArticleComponent } from './components';
+import { FeedbackModule } from '@valor-software/feedback';
+import { SwiperModule } from 'swiper/angular';
+
+@NgModule({
+ declarations: [
+ BlogPageComponent,
+ BlogComponent,
+ ArticleComponent,
+ ],
+ imports: [
+ CommonModule,
+ RouterModule.forChild(routes),
+ CommonDocsModule,
+ FeedbackModule,
+ SwiperModule
+ ]
+})
+export class BlogModule {
+}
+
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/article.component.html b/libs/route-pages/blog/src/components/article/article.component.html
similarity index 100%
rename from libs/route-pages/blog-portfolio/src/article.component.html
rename to libs/route-pages/blog/src/components/article/article.component.html
diff --git a/libs/route-pages/blog/src/components/article/article.component.ts b/libs/route-pages/blog/src/components/article/article.component.ts
new file mode 100644
index 000000000..da5ca4020
--- /dev/null
+++ b/libs/route-pages/blog/src/components/article/article.component.ts
@@ -0,0 +1,237 @@
+import { Component, Inject, OnDestroy } from '@angular/core';
+import { DomSanitizer } from '@angular/platform-browser';
+import { NavigationEnd, Router } from '@angular/router';
+import {
+ checkHTMLExtension,
+ GetArticlesService,
+ IArticle,
+ OLD_ROUTES_FROM_OLD_SITE
+} from '@valor-software/common-docs';
+import { filter, switchMap, catchError } from 'rxjs/operators';
+import { Subscription, of } from 'rxjs';
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'article',
+ styles: [`
+ ::ng-deep.turbo-table {
+ margin-top: 25px;
+ }
+
+ ::ng-deep.turbo-table tbody tr:not(:first-of-type) {
+ border-top: 1px solid gray;
+ }
+
+ ::ng-deep.turbo-table tbody tr:not(:first-of-type) td:not(:last-of-type) {
+ border-right: 1px solid gray
+ }
+
+ ::ng-deep.turbo-table tbody tr:not(:first-of-type) td {
+ padding: 5px 10px;
+ }
+
+ ::ng-deep tbody tr:first-of-type {
+ text-align: center;
+ }
+
+ ::ng-deep mark {
+ background-color: #A9A9A9;
+ color: #383838;
+ border-radius: 0.3em;
+ padding: 0.1em 0.25em;
+ }
+
+ ::ng-deep.white {
+ color: #ffffff;
+ }
+
+ ::ng-deep.small-img {
+ margin: auto;
+ width: 40%
+ }
+
+ ::ng-deep.block-citation {
+ border-left-width: 8px;
+ --tw-border-opacity: 1;
+ border-color: rgba(32, 32, 32, var(--tw-border-opacity));
+ --tw-bg-opacity: 1;
+ background-color: #2c2c2d;
+ }
+
+ ::ng-deep.block-citation > .attribution {
+ padding: 0 16px 16px 16px;
+ text-align: right;
+ }
+
+ ::ng-deep.block-citation > blockquote {
+ border: 0px;
+ border-radius: 3rem;
+ }
+
+ ::ng-deep.block-citation > blockquote > .paragraph:first-of-type:before {
+ content: open-quote;
+ float: left;
+ font-size: 3em;
+ margin-right: 4px;
+ font-weight: 700;
+ line-height: 0.6em;
+ color: rgba(226, 78, 99, var(--tw-text-opacity));
+ }
+
+ ::ng-deep.block-citation > blockquote > .paragraph:first-of-type:after {
+ content: no-close-quote;
+ }
+
+ `],
+ templateUrl: './article.component.html'
+})
+export class ArticleComponent implements OnDestroy {
+ changeBreadCrumbTitle?: { path: string, title: string }[];
+ article?: IArticle;
+ $routEvents?: Subscription;
+ linksFromOldSite?: { [key: string]: string };
+
+ constructor(
+ private router: Router,
+ private getArticleServ: GetArticlesService,
+ private sanitizer: DomSanitizer,
+ @Inject(OLD_ROUTES_FROM_OLD_SITE) linkList: { [key: string]: string },
+ ) {
+ this.linksFromOldSite = linkList;
+ this.$routEvents = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event) => {
+ this.checkRoutePath();
+ });
+
+ if (!this.article) {
+ this.checkRoutePath();
+ }
+ }
+
+ checkRoutePath() {
+ let artTitle = this.router.parseUrl(this.router.url).root.children.primary.segments[1].path;
+ if (!artTitle) {
+ this.router.navigate(['404']);
+ }
+
+ if (artTitle) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ artTitle = this.linksFromOldSite[artTitle] ? this.linksFromOldSite[artTitle] : artTitle;
+ artTitle = checkHTMLExtension(artTitle);
+ this.getArticleServ.getArticleRequest(artTitle).pipe(
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ switchMap((art) => {
+ this.article = art;
+ this.changeBreadCrumbTitle = [{
+ path: this.router.parseUrl(this.router.url).root.children.primary.segments[1].path,
+ title: art.title
+ }];
+ return this.getArticleServ.getHTMLSource(artTitle);
+ }),
+ catchError(error => {
+ if (!this.article) {
+ this.router.navigate(['404']);
+ }
+ return of();
+ })
+ ).subscribe(res => {
+ if (this.article) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ this.article.content = res;
+ this.addScriptsToHead();
+ }
+ }, error => {
+ this.router.navigate(['404']);
+ });
+ }
+ }
+
+ checkHTML(html: string) {
+ return this.sanitizer.bypassSecurityTrustHtml(html);
+ }
+
+ routLink(event: any) {
+ const element = event.target;
+
+ if (element.nodeName === 'A' && element.getAttribute('routerLink')) {
+ event.preventDefault();
+ const link = element.getAttribute('routerLink');
+ this.router.navigate([link]);
+ }
+
+ if (element.nodeName === 'A' && element.getAttribute('href')) {
+ const link = element.getAttribute('href');
+ if (link.includes('#')) {
+ event.preventDefault();
+ let url = this.router.url;
+ if (url.indexOf('#') > -1) {
+ url = url.substring(0, url.indexOf('#'));
+ }
+
+ if (url.indexOf('%23') > -1) {
+ url = url.substring(0, url.indexOf('%23'));
+ }
+
+ if (link) {
+ this.router.navigate([url.trim() + '/'], { fragment: link.replace('#', '') });
+ }
+ }
+ }
+ }
+
+ ngOnDestroy() {
+ this.$routEvents?.unsubscribe();
+ this.removeOldMicroDAta();
+ }
+
+ addScriptsToHead() {
+ this.removeOldMicroDAta();
+ const head = document.getElementsByTagName('head')[0];
+ const script = document.createElement('script');
+ script.setAttribute('id', 'article-micro-data');
+ script.setAttribute('type', 'application/ld+json');
+ script.innerHTML = `
+ {
+ "@context": "https://schema.org/",
+ "@type": "BlogPosting",
+ "mainEntityOfPage": {
+ "@type": "WebPage",
+ "@id": "https://valor-software.com${this.router.url}"
+ },
+ "headline": "${this.article?.title}",
+ "description": "${this.article?.seoDescription}",
+ "image": {
+ "@type": "ImageObject",
+ "url": "https://valor-software.com/${this.article?.bgImg}",
+ "width": "",
+ "height": ""
+ },
+ "author": {
+ "@type": "Organization",
+ "name": "${this.article?.author}"
+ },
+ "publisher": {
+ "@type": "Organization",
+ "name": "Valor Software",
+ "logo": {
+ "@type": "ImageObject",
+ "url": "https://valor-software.com/assets/img/valor_img/valor-logo.svg",
+ "width": "",
+ "height": ""
+ }
+ },
+ "datePublished": "${this.article?.date}"
+ }
+ `;
+ head.insertBefore(script, head.firstChild);
+ }
+
+ removeOldMicroDAta() {
+ const oldMicroDAta = document.getElementById('article-micro-data');
+ if (oldMicroDAta) {
+ oldMicroDAta.remove();
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/blog.component.html b/libs/route-pages/blog/src/components/blog/blog.component.html
similarity index 100%
rename from libs/route-pages/blog-portfolio/src/blog.component.html
rename to libs/route-pages/blog/src/components/blog/blog.component.html
diff --git a/libs/route-pages/blog/src/components/blog/blog.component.ts b/libs/route-pages/blog/src/components/blog/blog.component.ts
new file mode 100644
index 000000000..f2d28bc30
--- /dev/null
+++ b/libs/route-pages/blog/src/components/blog/blog.component.ts
@@ -0,0 +1,116 @@
+import { AfterViewInit, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core';
+import { GetArticlesService, titleRefactoring } from '@valor-software/common-docs';
+import { Subscription } from 'rxjs';
+import { IArticle } from '@valor-software/common-docs';
+import { Router } from '@angular/router';
+
+export const Domains = {
+ business_analysis: 'Business Analysis',
+ user_research_design: 'User Research & Design',
+ dev_quality_assurance: 'Development & Quality Assurance',
+ devops_cloud: 'DevOps & Cloud',
+ recruitment_pm: 'Recruitment & Project Mgmt.',
+ sales_marketing: 'Sales & Marketing',
+ module_federation: 'Module Federation',
+ other: 'Other'
+};
+
+export const Languages = {
+ en: 'English',
+ pt: 'Portuguese'
+};
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'blog-block',
+ templateUrl: './blog.component.html'
+})
+export class BlogComponent implements OnDestroy, AfterViewInit {
+ sortList: string[] = [];
+ sortLang: string[] = [];
+ $articles?: Subscription;
+ articles?: IArticle[];
+ sortArticles?: IArticle[] = [];
+ activeIndex: string[] = [];
+ showAll = false;
+ isCollapsed = true;
+
+ @Input() set _articles(value: IArticle[]) {
+ this.articles = Object.assign(value);
+ this.sortArticles = Object.assign(value);
+ }
+
+ constructor(
+ private router: Router,
+ private getArticles: GetArticlesService,
+ private cdr: ChangeDetectorRef,
+ ) {
+ this.getSortKeys();
+ }
+
+ ngAfterViewInit(): void {
+ this.toggleLanguage('en');
+ }
+
+ getSortKeys() {
+ const sortSet = new Set();
+ Object.keys(Domains).map(key => sortSet.add(key));
+ this.sortList = [...sortSet];
+
+ const sortLang = new Set();
+ Object.keys(Languages).map(key => sortLang.add(key));
+ this.sortLang = [...sortLang];
+ }
+
+ getDomainTitle(key: string) {
+ const resKey = key as keyof typeof Domains;
+ return Domains[resKey];
+ }
+
+ getLanguageTitle(key: string) {
+ const resKey = key as keyof typeof Languages;
+ return Languages[resKey];
+ }
+
+ toggleActiveIndex(key: string) {
+ if (this.activeIndex.includes(key)) {
+ this.activeIndex = this.activeIndex.filter(item => item !== key);
+ this.showAll = false;
+ return;
+ }
+
+ this.activeIndex = [...this.activeIndex, key];
+ this.showAll = false;
+ }
+
+ toggleLanguage(key: string) {
+ if (!this.activeIndex.includes(key)) {
+ const keys = this.activeIndex.filter(item => item !== 'pt' && item !== 'en');
+ this.activeIndex = [...keys, key];
+ }
+
+ this.showAll = false;
+ }
+
+ updateArticles(articles: IArticle[] | []) {
+ this.sortArticles = articles;
+ this.cdr.detectChanges();
+ }
+
+ resetAll() {
+ const lang = this.activeIndex.includes('pt') ? 'pt' : 'en';
+ this.activeIndex = [lang];
+ }
+
+ getRouteLink(link: string): any {
+ return titleRefactoring(link);
+ }
+
+ checkLength(): boolean {
+ return !!(this.sortArticles?.length && this.sortArticles?.length > 8);
+ }
+
+ ngOnDestroy() {
+ this.$articles?.unsubscribe();
+ }
+}
\ No newline at end of file
diff --git a/libs/route-pages/blog/src/components/index.ts b/libs/route-pages/blog/src/components/index.ts
new file mode 100644
index 000000000..9c586faa2
--- /dev/null
+++ b/libs/route-pages/blog/src/components/index.ts
@@ -0,0 +1,2 @@
+export * from './article/article.component';
+export * from './blog/blog.component';
diff --git a/libs/route-pages/blog/src/index.ts b/libs/route-pages/blog/src/index.ts
new file mode 100644
index 000000000..619cd2db3
--- /dev/null
+++ b/libs/route-pages/blog/src/index.ts
@@ -0,0 +1,2 @@
+export * from './blog.module';
+
\ No newline at end of file
diff --git a/libs/route-pages/blog/src/routes.ts b/libs/route-pages/blog/src/routes.ts
new file mode 100644
index 000000000..62b174cb5
--- /dev/null
+++ b/libs/route-pages/blog/src/routes.ts
@@ -0,0 +1,21 @@
+import { BlogPageComponent } from './blog-page.component';
+import { Routes } from '@angular/router';
+import { ArticleComponent } from './components';
+
+export const routes: Routes = [
+ {
+ path: '',
+ children: [
+ {
+ path: '',
+ pathMatch: 'full',
+ component: BlogPageComponent
+ },
+ {
+ path: ':id',
+ component: ArticleComponent
+ }
+ ]
+ }
+];
+
diff --git a/libs/route-pages/blog-portfolio/src/services/getBlogs.service.ts b/libs/route-pages/blog/src/services/getBlogs.service.ts
similarity index 100%
rename from libs/route-pages/blog-portfolio/src/services/getBlogs.service.ts
rename to libs/route-pages/blog/src/services/getBlogs.service.ts
diff --git a/libs/route-pages/blog/src/test-setup.ts b/libs/route-pages/blog/src/test-setup.ts
new file mode 100644
index 000000000..ae5cbec72
--- /dev/null
+++ b/libs/route-pages/blog/src/test-setup.ts
@@ -0,0 +1,12 @@
+import 'jest-preset-angular/setup-jest';
+
+import { getTestBed } from '@angular/core/testing';
+import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
+
+getTestBed().resetTestEnvironment();
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting(),
+ { teardown: { destroyAfterEach: false } },
+);
+
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/tsconfig.json b/libs/route-pages/blog/tsconfig.json
similarity index 100%
rename from libs/route-pages/blog-portfolio/tsconfig.json
rename to libs/route-pages/blog/tsconfig.json
diff --git a/libs/route-pages/blog-portfolio/tsconfig.lib.json b/libs/route-pages/blog/tsconfig.lib.json
similarity index 100%
rename from libs/route-pages/blog-portfolio/tsconfig.lib.json
rename to libs/route-pages/blog/tsconfig.lib.json
diff --git a/libs/route-pages/blog-portfolio/tsconfig.lib.prod.json b/libs/route-pages/blog/tsconfig.lib.prod.json
similarity index 100%
rename from libs/route-pages/blog-portfolio/tsconfig.lib.prod.json
rename to libs/route-pages/blog/tsconfig.lib.prod.json
diff --git a/libs/route-pages/blog-portfolio/tsconfig.spec.json b/libs/route-pages/blog/tsconfig.spec.json
similarity index 100%
rename from libs/route-pages/blog-portfolio/tsconfig.spec.json
rename to libs/route-pages/blog/tsconfig.spec.json
diff --git a/libs/route-pages/projects/.eslintrc.json b/libs/route-pages/projects/.eslintrc.json
new file mode 100644
index 000000000..b3154935a
--- /dev/null
+++ b/libs/route-pages/projects/.eslintrc.json
@@ -0,0 +1,36 @@
+{
+ "extends": ["../../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts"],
+ "rules": {
+ "@angular-eslint/directive-selector": [
+ "error",
+ {
+ "type": "attribute",
+ "prefix": "valorSoftwareSiteBase",
+ "style": "camelCase"
+ }
+ ],
+ "@angular-eslint/component-selector": [
+ "error",
+ {
+ "type": "element",
+ "prefix": "valor-software-site-base",
+ "style": "kebab-case"
+ }
+ ]
+ },
+ "extends": [
+ "plugin:@nx/angular",
+ "plugin:@angular-eslint/template/process-inline-templates"
+ ]
+ },
+ {
+ "files": ["*.html"],
+ "extends": ["plugin:@nx/angular-template"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/libs/route-pages/projects/ng-package.json b/libs/route-pages/projects/ng-package.json
new file mode 100644
index 000000000..de0b1921e
--- /dev/null
+++ b/libs/route-pages/projects/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
+ "dest": "../../../dist/libs/route-pages/projects",
+ "lib": {
+ "entryFile": "src/index.ts"
+ }
+}
diff --git a/libs/route-pages/projects/package.json b/libs/route-pages/projects/package.json
new file mode 100644
index 000000000..81f9e6586
--- /dev/null
+++ b/libs/route-pages/projects/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@valor-software/projects",
+ "version": "0.0.1",
+ "peerDependencies": {
+ "@angular/common": "^12.2.0",
+ "@angular/core": "^12.2.0"
+ },
+ "dependencies": {
+ "tslib": "^2.3.0"
+ }
+}
diff --git a/libs/route-pages/projects/project.json b/libs/route-pages/projects/project.json
new file mode 100644
index 000000000..3fd82e9b2
--- /dev/null
+++ b/libs/route-pages/projects/project.json
@@ -0,0 +1,51 @@
+{
+ "name": "route-pages-projects",
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "libs/route-pages/projects/src",
+ "prefix": "valor-software-site-base",
+ "tags": [],
+ "projectType": "library",
+ "targets": {
+ "build": {
+ "executor": "@nx/angular:ng-packagr-lite",
+ "outputs": [
+ "dist/libs/route-pages/projects"
+ ],
+ "options": {
+ "project": "libs/route-pages/projects/ng-package.json"
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "libs/route-pages/projects/tsconfig.lib.prod.json"
+ },
+ "development": {
+ "tsConfig": "libs/route-pages/projects/tsconfig.lib.json"
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "test": {
+ "executor": "@nx/jest:jest",
+ "outputs": [
+ "coverage/libs/route-pages/projects"
+ ],
+ "options": {
+ "jestConfig": "libs/route-pages/projects/jest.config.ts",
+ "passWithNoTests": true
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "options": {
+ "lintFilePatterns": [
+ "libs/route-pages/projects/**/*.ts",
+ "libs/route-pages/projects/**/*.html"
+ ]
+ }
+ }
+ },
+ "implicitDependencies": [
+ "common-docs",
+ "feedback"
+ ]
+}
diff --git a/libs/route-pages/projects/src/index.ts b/libs/route-pages/projects/src/index.ts
new file mode 100644
index 000000000..59ce02a60
--- /dev/null
+++ b/libs/route-pages/projects/src/index.ts
@@ -0,0 +1 @@
+export * from './lib/projects.module';
diff --git a/libs/route-pages/projects/src/lib/components/index.ts b/libs/route-pages/projects/src/lib/components/index.ts
new file mode 100644
index 000000000..53dee3dc0
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/components/index.ts
@@ -0,0 +1,2 @@
+export * from './project/project.component';
+export * from './projects-block/projects-block.component';
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/project.component.html b/libs/route-pages/projects/src/lib/components/project/project.component.html
similarity index 100%
rename from libs/route-pages/blog-portfolio/src/project.component.html
rename to libs/route-pages/projects/src/lib/components/project/project.component.html
diff --git a/libs/route-pages/projects/src/lib/components/project/project.component.ts b/libs/route-pages/projects/src/lib/components/project/project.component.ts
new file mode 100644
index 000000000..e068bb8bb
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/components/project/project.component.ts
@@ -0,0 +1,73 @@
+import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
+import { Subscription } from 'rxjs';
+import { NavigationEnd, Router } from '@angular/router';
+import { filter } from 'rxjs/operators';
+import { IPortfolio, GetPortfolioService, UtilService } from '@valor-software/common-docs';
+import { checkHTMLExtension, titleRefactoring } from '@valor-software/common-docs';
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'project',
+ templateUrl: 'project.component.html'
+})
+export class ProjectComponent implements OnDestroy {
+ changeBreadCrumbTitle?: { path: string, title: string }[];
+ project?: IPortfolio;
+ $routEvents?: Subscription;
+
+ constructor(
+ public utilService: UtilService,
+ private router: Router,
+ private getProjectsServ: GetPortfolioService,
+ private cdr: ChangeDetectorRef
+ ) {
+ this.$routEvents = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event) => {
+ this.checkRoutePath();
+ });
+
+ if (!this.project) {
+ this.checkRoutePath();
+ }
+ }
+
+ checkRoutePath() {
+ let artTitle = this.router.parseUrl(this.router.url).root.children.primary.segments[1].path;
+ if (!artTitle) {
+ this.router.navigate(['/404']);
+ }
+
+ artTitle = checkHTMLExtension(artTitle);
+ this.getProjectsServ.getPortfolioRequest(artTitle).subscribe((res: IPortfolio) => {
+ this.changeBreadCrumbTitle = [{
+ path: this.router.parseUrl(this.router.url).root.children.primary.segments[1].path,
+ title: res.name
+ }];
+ this.project = res;
+ }, error => {
+ console.log('error', error);
+ this.router.navigate(['/404']);
+ });
+ }
+
+ getRouteLink(link: string): string {
+ return titleRefactoring(link);
+ }
+
+ getRespSrc(link: string): string {
+ const arr = link.split('.');
+ return `${arr[0]}_resp.${arr[1]}`;
+ }
+
+ changeSrc(event: Event, link: string) {
+ (event.target as HTMLImageElement).src = link;
+ this.cdr.detectChanges();
+ }
+
+ checkLength(arr: Array, number: number): boolean {
+ return arr?.length > number;
+ }
+
+ ngOnDestroy() {
+ this.$routEvents?.unsubscribe();
+ }
+}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/projects-block.component.html b/libs/route-pages/projects/src/lib/components/projects-block/projects-block.component.html
similarity index 100%
rename from libs/route-pages/blog-portfolio/src/projects-block.component.html
rename to libs/route-pages/projects/src/lib/components/projects-block/projects-block.component.html
diff --git a/libs/route-pages/projects/src/lib/components/projects-block/projects-block.component.ts b/libs/route-pages/projects/src/lib/components/projects-block/projects-block.component.ts
new file mode 100644
index 000000000..21ff0526e
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/components/projects-block/projects-block.component.ts
@@ -0,0 +1,86 @@
+import { ChangeDetectorRef, Component, Input } from '@angular/core';
+import { Router } from '@angular/router';
+import { IPortfolio, titleRefactoring } from '@valor-software/common-docs';
+
+const SortList = {
+ all_projects: 'All Projects',
+ web: 'Web',
+ mobile: 'Mobile',
+ ui: 'UI/UX',
+ migration: 'Migration',
+ art_intel: 'Artificial Intelligence'
+};
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'projects-block',
+ templateUrl: './projects-block.component.html'
+})
+export class ProjectsBlockComponent {
+ sortList?: string[];
+ projects?: IPortfolio[];
+ sortProjects?: IPortfolio[] = [];
+ activeIndex: string[] = ['all_projects'];
+ showAll = false;
+
+ @Input() set _projects(value: IPortfolio[]) {
+ this.projects = Object.assign(value);
+ this.updateProjects(value);
+ }
+
+ constructor(
+ private router: Router,
+ private cdr: ChangeDetectorRef,
+ ) {
+ this.getSortKeys();
+ }
+
+ getSortKeys() {
+ const sortSet = new Set();
+ Object.keys(SortList).map(key => sortSet.add(key));
+ this.sortList = [...sortSet];
+ }
+
+ getSortTitle(key: string) {
+ const resKey = key as keyof typeof SortList;
+ return SortList[resKey];
+ }
+
+ toggleActiveIndex(key: string) {
+ if (this.activeIndex.includes(key)) {
+ this.activeIndex = this.activeIndex.filter(item => item !== key);
+ if (!this.activeIndex.length) {
+ this.resetAll();
+ }
+
+ this.showAll = false;
+ return;
+ }
+
+ if (key) {
+ this.activeIndex = this.activeIndex.filter(item => item !== 'all_projects');
+ }
+
+ this.activeIndex = [...this.activeIndex, key];
+ this.showAll = false;
+ }
+
+ resetAll() {
+ this.activeIndex = ['all_projects'];
+ }
+
+ checkLength(): boolean {
+ return !!(this.sortProjects?.length && this.sortProjects?.length > 8);
+ }
+
+ getRouteLink(link: string): any {
+ return titleRefactoring(link);
+ }
+
+ updateProjects(projects: IPortfolio[]) {
+ if (projects) {
+ this.sortProjects = Object.assign(projects);
+ this.cdr.detectChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/route-pages/blog-portfolio/src/directives/sort.directive.ts b/libs/route-pages/projects/src/lib/directives/sort.directive.ts
similarity index 100%
rename from libs/route-pages/blog-portfolio/src/directives/sort.directive.ts
rename to libs/route-pages/projects/src/lib/directives/sort.directive.ts
diff --git a/libs/route-pages/projects/src/lib/projects-page.component.html b/libs/route-pages/projects/src/lib/projects-page.component.html
new file mode 100644
index 000000000..a914e2f70
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/projects-page.component.html
@@ -0,0 +1,77 @@
+
+ 0 && activeProject">
+
+
+
+
+ {{activeProject?.name | customSlice: 40}}
+
+
+ {{activeProject?.description | customSlice: 300}}
+
+
+
+
+
+
+
Recent projects
+
+
+
+
+
+
+
+
+ Projects
+ 0" class="container pb-5 flex justify-between items-center md:pt-8 lg:pt-16"
+ style="max-height: 100%;">
+
+
+
+
+
diff --git a/libs/route-pages/projects/src/lib/projects-page.component.ts b/libs/route-pages/projects/src/lib/projects-page.component.ts
new file mode 100644
index 000000000..ef80714d4
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/projects-page.component.ts
@@ -0,0 +1,77 @@
+import { Component, OnDestroy } from '@angular/core';
+import { NavigationEnd, Router } from '@angular/router';
+import { filter } from 'rxjs/operators';
+import { forkJoin, Subscription } from 'rxjs';
+import { GetPortfolioService, IPortfolio, titleRefactoring } from '@valor-software/common-docs';
+import SwiperCore, { Pagination, SwiperOptions } from 'swiper';
+
+SwiperCore.use([Pagination]);
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'projects-page',
+ templateUrl: './projects-page.component.html'
+})
+export class ProjectsPageComponent implements OnDestroy {
+ routeUrl = '';
+ $generalSubscription = new Subscription();
+ firstProjects: IPortfolio[] = [];
+ projects: IPortfolio[] = [];
+ activeProject?: IPortfolio;
+
+ swiperConfig: SwiperOptions = {
+ slidesPerView: 1,
+ spaceBetween: 40,
+ centeredSlides: true,
+ initialSlide: 0,
+ pagination: {
+ clickable: true
+ }
+ };
+
+ constructor(
+ private readonly router: Router,
+ private readonly getPortfolio: GetPortfolioService,
+ ) {
+ this.$generalSubscription.add(
+ this.router.events.pipe(
+ filter(event => event instanceof NavigationEnd)
+ ).subscribe(event => {
+ this.routeUrl = this.router.parseUrl(this.router.url).root.children['primary']?.segments[0].path;
+ this._initObserveFullListOfProjects();
+ }));
+ }
+
+ getFirstProjects(value: Type[]): Type[] {
+ return value.slice(0, 4);
+ }
+
+ getRouteLink(link: string): any {
+ return titleRefactoring(link);
+ }
+
+ filterFirstItems() {
+ if (this.activeProject) {
+ this.firstProjects = this.firstProjects?.filter(item => item !== this.activeProject);
+ }
+ }
+
+ ngOnDestroy() {
+ this.$generalSubscription.unsubscribe();
+ }
+
+ private _initObserveFullListOfProjects() {
+ this.$generalSubscription.add(
+ forkJoin(
+ this.getPortfolio.getFullListOfPortfolio()
+ ).subscribe((res?: IPortfolio[]) => {
+ if (res) {
+ this.projects = Object.assign(res);
+ this.firstProjects = this.getFirstProjects(res);
+ this.activeProject = this.firstProjects[0];
+ this.filterFirstItems();
+ }
+ })
+ );
+ }
+}
\ No newline at end of file
diff --git a/libs/route-pages/projects/src/lib/projects.module.ts b/libs/route-pages/projects/src/lib/projects.module.ts
new file mode 100644
index 000000000..88ecc121a
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/projects.module.ts
@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ProjectsBlockComponent, ProjectComponent } from './components';
+import { CommonDocsModule } from '@valor-software/common-docs';
+import { FeedbackModule } from '@valor-software/feedback';
+import { SwiperModule } from 'swiper/angular';
+import { RouterModule } from '@angular/router';
+import { routes } from './routes';
+import { ProjectsPageComponent } from './projects-page.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ RouterModule.forChild(routes),
+ CommonDocsModule,
+ FeedbackModule,
+ SwiperModule
+ ],
+ declarations: [
+ ProjectsPageComponent,
+ ProjectComponent,
+ ProjectsBlockComponent,
+ ]
+})
+export class ProjectsModule {
+}
diff --git a/libs/route-pages/projects/src/lib/routes.ts b/libs/route-pages/projects/src/lib/routes.ts
new file mode 100644
index 000000000..4bebd7eec
--- /dev/null
+++ b/libs/route-pages/projects/src/lib/routes.ts
@@ -0,0 +1,50 @@
+import { Routes } from '@angular/router';
+import { ProjectComponent } from './components';
+import { ProjectsPageComponent } from './projects-page.component';
+
+
+export const routes: Routes = [
+ {
+ path: '',
+ children: [
+ {
+ path: '',
+ pathMatch: 'full',
+ component: ProjectsPageComponent
+ },
+ {
+ path: 'booking',
+ loadChildren: () => import('@valor-software/booking-page').then(m => m.BookingPageModule)
+ },
+ {
+ path: 'terminus',
+ loadChildren: () => import('@valor-software/terminus-page').then(m => m.TerminusPageModule)
+ },
+ {
+ path: 'ashes-of-creation',
+ loadChildren: () => import('@valor-software/ashes-page').then(m => m.AshesPageModule)
+ },
+ {
+ path: 'dollar-street',
+ loadChildren: () => import('@valor-software/dollar-street-page').then(m => m.DollarStreetPageModule)
+ },
+ {
+ path: 'tablesready',
+ loadChildren: () => import('@valor-software/tablesready-page').then(m => m.TablesReadyPageModule)
+ },
+ {
+ path: 'liberty-flights',
+ loadChildren: () => import('@valor-software/liberty-flights-page').then(m => m.LibertyFlightsPageModule)
+ },
+ {
+ path: 'breethe',
+ loadChildren: () => import('@valor-software/breethe-page').then(m => m.BreethePageModule)
+ },
+ {
+ path: ':id',
+ component: ProjectComponent
+ }
+ ]
+ }
+];
+
diff --git a/libs/route-pages/projects/src/test-setup.ts b/libs/route-pages/projects/src/test-setup.ts
new file mode 100644
index 000000000..35a438c72
--- /dev/null
+++ b/libs/route-pages/projects/src/test-setup.ts
@@ -0,0 +1,12 @@
+import 'jest-preset-angular/setup-jest';
+
+import { getTestBed } from '@angular/core/testing';
+import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
+
+getTestBed().resetTestEnvironment();
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting(),
+ { teardown: { destroyAfterEach: false } },
+);
+
\ No newline at end of file
diff --git a/libs/route-pages/projects/tsconfig.json b/libs/route-pages/projects/tsconfig.json
new file mode 100644
index 000000000..aeb1c9ace
--- /dev/null
+++ b/libs/route-pages/projects/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "target": "es2020"
+ },
+ "angularCompilerOptions": {
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true
+ }
+}
diff --git a/libs/route-pages/projects/tsconfig.lib.json b/libs/route-pages/projects/tsconfig.lib.json
new file mode 100644
index 000000000..5aebe84f5
--- /dev/null
+++ b/libs/route-pages/projects/tsconfig.lib.json
@@ -0,0 +1,20 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../../dist/out-tsc",
+ "target": "ES2022",
+ "declaration": true,
+ "declarationMap": true,
+ "inlineSources": true,
+ "types": [],
+ "lib": ["dom", "es2018"],
+ "useDefineForClassFields": false
+ },
+ "exclude": [
+ "src/test-setup.ts",
+ "**/*.spec.ts",
+ "**/*.test.ts",
+ "jest.config.ts"
+ ],
+ "include": ["**/*.ts"]
+}
diff --git a/libs/route-pages/projects/tsconfig.lib.prod.json b/libs/route-pages/projects/tsconfig.lib.prod.json
new file mode 100644
index 000000000..0e06848ce
--- /dev/null
+++ b/libs/route-pages/projects/tsconfig.lib.prod.json
@@ -0,0 +1,11 @@
+{
+ "extends": "./tsconfig.lib.json",
+ "compilerOptions": {
+ "declarationMap": false,
+ "target": "ES2022",
+ "useDefineForClassFields": false
+ },
+ "angularCompilerOptions": {
+ "compilationMode": "partial"
+ }
+}
diff --git a/libs/route-pages/projects/tsconfig.spec.json b/libs/route-pages/projects/tsconfig.spec.json
new file mode 100644
index 000000000..cb7b2fe45
--- /dev/null
+++ b/libs/route-pages/projects/tsconfig.spec.json
@@ -0,0 +1,20 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../../dist/out-tsc",
+ "module": "commonjs",
+ "types": [
+ "jest",
+ "node"
+ ]
+ },
+ "files": [
+ "src/test-setup.ts"
+ ],
+ "include": [
+ "**/*.test.ts",
+ "**/*.spec.ts",
+ "**/*.d.ts",
+ "jest.config.ts"
+ ]
+}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 59c750f97..2dfbea4d7 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -10,20 +10,22 @@
"importHelpers": true,
"target": "es2015",
"module": "esnext",
- "lib": ["es2017", "dom"],
- "types": ["node"],
+ "lib": [
+ "es2017",
+ "dom"
+ ],
+ "types": [
+ "node"
+ ],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
- "@valor-software/module-federation-page": [
- "libs/route-pages/module-federation-page/src/index.ts"
- ],
"@valor-software/ashes-page": [
"libs/route-pages/ashes-page/src/index.ts"
],
- "@valor-software/blog-portfolio": [
- "libs/route-pages/blog-portfolio/src/index.ts"
+ "@valor-software/blog": [
+ "libs/route-pages/blog/src/index.ts"
],
"@valor-software/booking-page": [
"libs/route-pages/booking-page/src/index.ts"
@@ -31,23 +33,39 @@
"@valor-software/breethe-page": [
"libs/route-pages/breethe-page/src/index.ts"
],
- "@valor-software/careers": ["libs/route-pages/careers/src/index.ts"],
- "@valor-software/common-docs": ["libs/common-docs/src/index.ts"],
+ "@valor-software/careers": [
+ "libs/route-pages/careers/src/index.ts"
+ ],
+ "@valor-software/common-docs": [
+ "libs/common-docs/src/index.ts"
+ ],
"@valor-software/dollar-street-page": [
"libs/route-pages/dollar-street-page/src/index.ts"
],
- "@valor-software/feedback": ["libs/feedback/src/index.ts"],
- "@valor-software/file-uploader": ["libs/file-uploader/src/index.ts"],
+ "@valor-software/feedback": [
+ "libs/feedback/src/index.ts"
+ ],
+ "@valor-software/file-uploader": [
+ "libs/file-uploader/src/index.ts"
+ ],
"@valor-software/for-clients": [
"libs/route-pages/for-clients/src/index.ts"
],
- "@valor-software/home-page": ["libs/route-pages/home-page/src/index.ts"],
+ "@valor-software/home-page": [
+ "libs/route-pages/home-page/src/index.ts"
+ ],
"@valor-software/liberty-flights-page": [
"libs/route-pages/liberty-flights-page/src/index.ts"
],
+ "@valor-software/module-federation-page": [
+ "libs/route-pages/module-federation-page/src/index.ts"
+ ],
"@valor-software/press-release": [
"libs/route-pages/press-release/src/index.ts"
],
+ "@valor-software/projects": [
+ "libs/route-pages/projects/src/index.ts"
+ ],
"@valor-software/privacy-policy-page": [
"libs/route-pages/privacy-policy-page/src/index.ts"
],
@@ -68,5 +86,8 @@
]
}
},
- "exclude": ["node_modules", "tmp"]
+ "exclude": [
+ "node_modules",
+ "tmp"
+ ]
}