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 @@ +
+ +
+
+
+

+ {{activeArticle?.title | customSlice: 40}} +

+

+ {{activeArticle?.seoDescription | customSlice: 300}} +

+ +
+ +
+

Latest Articles

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

Articles

+
+ +
+
+ + 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 @@ +
+ +
+
+
+

+ {{activeProject?.name | customSlice: 40}} +

+

+ {{activeProject?.description | customSlice: 300}} +

+ + +
+ +
+

Recent projects

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

Projects

+
+ +
+
+ + 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" + ] }