From b9fb7c6bcd7beff0bd4fa28a370d9e1ce4436cee Mon Sep 17 00:00:00 2001 From: VladyslavPavlysko Date: Mon, 29 Jul 2024 08:28:46 +0300 Subject: [PATCH 01/26] fix emtpy space, do NOT reasign streetcodeArtSlides.... --- .../ArtGallery/ArtGalleryBlock.component.tsx | 4 ++-- src/app/stores/streetcode-art-slide-store.ts | 11 ++++++++--- src/features/SlickSlider/SlickSlider.component.tsx | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx b/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx index 12e43ea33..ae009fc06 100644 --- a/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx +++ b/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx @@ -90,9 +90,9 @@ const ArtGallery = ({ if (streetcodeIdValidAndFetchingRequired()) { secondRender.current = true; if (isFillArtsStore) { - await fetchAllToDefaultTemplate(getStreetCodeId !== -1 ? getStreetCodeId : parseId); + const startingSlide = await fetchAllToDefaultTemplate(getStreetCodeId !== -1 ? getStreetCodeId : parseId); - let currentSlide = 0; + let currentSlide = startingSlide ?? 0; while (currentSlide < MAX_SLIDES_AMOUNT) { try { // eslint-disable-next-line no-await-in-loop diff --git a/src/app/stores/streetcode-art-slide-store.ts b/src/app/stores/streetcode-art-slide-store.ts index ac555e2f8..23f37c92d 100644 --- a/src/app/stores/streetcode-art-slide-store.ts +++ b/src/app/stores/streetcode-art-slide-store.ts @@ -81,9 +81,14 @@ export default class StreetcodeArtSlideStore { } }; - public fetchAllToDefaultTemplate = async (streetcodeid: number) => { - const slidesCount = await StreetcodeArtApi.getAllCountByStreetcodeId(streetcodeid) - this.streetcodeArtSlides = new Array(slidesCount).fill(bindStreetcodeIdToDefaultSlide(streetcodeid), 0, slidesCount) + public fetchAllToDefaultTemplate = async (streetcodeid: number): Promise => { + if (!this.streetcodeWasFetched.includes(streetcodeid)) { + const startingPosition = this.streetcodeArtSlides.length; + const slidesCount = await StreetcodeArtApi.getAllCountByStreetcodeId(streetcodeid) + const placeholders = new Array(slidesCount).fill(bindStreetcodeIdToDefaultSlide(streetcodeid), 0, slidesCount); + this.streetcodeArtSlides.push(...placeholders); + return startingPosition; + } } public fetchAllArtSlidesByStreetcodeId = async (streetcodeid: number, startIndex: number) => { diff --git a/src/features/SlickSlider/SlickSlider.component.tsx b/src/features/SlickSlider/SlickSlider.component.tsx index d4d96dd4f..661922c9e 100644 --- a/src/features/SlickSlider/SlickSlider.component.tsx +++ b/src/features/SlickSlider/SlickSlider.component.tsx @@ -14,7 +14,7 @@ const GenericSlider: FC = ({ ...sliderProps }) => { const sliderRef = useRef(null); - + sliderRef.current?.slickGoTo(0); //Does anybody see issue with this? const handleClick = useCallback((index: number, direction: 'right' | 'left') => { if (sliderRef && sliderRef.current && swipeOnClick) { if (direction === 'right') { From 5a2de009cca39ffb16101e872813becc97487b2e Mon Sep 17 00:00:00 2001 From: Nazar Mykhailenko Date: Mon, 29 Jul 2024 20:44:25 +0300 Subject: [PATCH 02/26] Fix add link button in Team modal --- .../AdminPage/TeamPage/TeamModal/TeamModal.component.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx b/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx index 2b549b713..244496a1f 100644 --- a/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx +++ b/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx @@ -151,7 +151,7 @@ const TeamModal: React.FC<{ const onSuccesfulSubmitLinks = (formValues: any) => { const url = formValues.url as string; - const logotype = teamLinksForm.getFieldValue('logotype'); + const logotype = teamLinksForm.getFieldValue('logotype').split('.')[0]; setExistWarningVisible(false); setCustomWarningVisible(false); setInvalidWarningVisible(false); @@ -170,7 +170,7 @@ const TeamModal: React.FC<{ } else { const newId = getNewId(teamSourceLinks); const isLogoTypePresent = teamSourceLinks.some(obj => obj.logoType === Number(LogoType[logotype])); - + if(isLogoTypePresent){ setExistWarningVisible(true); } @@ -181,7 +181,7 @@ const TeamModal: React.FC<{ targetUrl: url, }]); } - + } }; From c53333cd5bbc13318bb3208973d454db8b720753 Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:19:32 +0300 Subject: [PATCH 03/26] add constants for mapping enum logo to the icon component --- .../TeamPage/TeamModal/constants/logoIcons.ts | 51 +++++++++++++++++++ .../TeamModal/constants/socialOptions.ts | 17 ++++++- src/models/team/team.model.ts | 2 +- 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/features/AdminPage/TeamPage/TeamModal/constants/logoIcons.ts diff --git a/src/features/AdminPage/TeamPage/TeamModal/constants/logoIcons.ts b/src/features/AdminPage/TeamPage/TeamModal/constants/logoIcons.ts new file mode 100644 index 000000000..3fef1a6db --- /dev/null +++ b/src/features/AdminPage/TeamPage/TeamModal/constants/logoIcons.ts @@ -0,0 +1,51 @@ +import { FunctionComponent, SVGAttributes } from 'react'; +import behance from '@assets/images/partners/behance.svg'; +import facebook from '@assets/images/partners/facebook.svg'; +import http from '@assets/images/partners/http.svg'; +import instagram from '@assets/images/partners/instagram.svg'; +import linkedin from '@assets/images/partners/linkedin.svg'; +import tiktok from '@assets/images/partners/tiktok.svg'; +import twitter from '@assets/images/partners/twitterNew.svg'; +import youtube from '@assets/images/partners/youtube.svg'; + +import { LogoType } from '@/models/team/team.model'; + +interface LogoIcon { + type: LogoType, + icon: FunctionComponent> +} +const LOGO_ICONS: LogoIcon[] = [ + { + type: LogoType.instagram, + icon: instagram, + }, + { + type: LogoType.facebook, + icon: facebook, + }, + { + type: LogoType.youtube, + icon: youtube, + }, + { + type: LogoType.linkedin, + icon: linkedin, + }, + { + type: LogoType.behance, + icon: behance, + }, + { + type: LogoType.tiktok, + icon: tiktok, + }, + { + type: LogoType.twitter, + icon: twitter, + }, + { + type: LogoType.http, + icon: http, + }, +]; +export default LOGO_ICONS; diff --git a/src/features/AdminPage/TeamPage/TeamModal/constants/socialOptions.ts b/src/features/AdminPage/TeamPage/TeamModal/constants/socialOptions.ts index 840be54fd..d74227def 100644 --- a/src/features/AdminPage/TeamPage/TeamModal/constants/socialOptions.ts +++ b/src/features/AdminPage/TeamPage/TeamModal/constants/socialOptions.ts @@ -1,35 +1,50 @@ -const SOCIAL_OPTIONS = [ +import { LogoType } from '@/models/team/team.model'; + +interface SocialItem { + label: string + value: string + logo: LogoType +} +const SOCIAL_OPTIONS: SocialItem[] = [ { value: 'x.com', label: 'X', + logo: LogoType.twitter, }, { value: 'instagram.com', label: 'Instagram', + logo: LogoType.instagram, }, { value: 'facebook.com', label: 'Facebook', + logo: LogoType.facebook, }, { value: 'youtube.com', label: 'Youtube', + logo: LogoType.youtube, }, { value: 'linkedin.com', label: 'LinkedIn', + logo: LogoType.linkedin, }, { value: 'tiktok.com', label: 'TikTok', + logo: LogoType.tiktok, }, { value: 'behance.net', label: 'Behance', + logo: LogoType.behance, }, { value: 'http', label: 'Ваш сайт', + logo: LogoType.http, }, ]; diff --git a/src/models/team/team.model.ts b/src/models/team/team.model.ts index f37b119b5..3a8a2ccf4 100644 --- a/src/models/team/team.model.ts +++ b/src/models/team/team.model.ts @@ -28,7 +28,7 @@ export interface TeamMemberLinkCreateUpdate { export interface TeamMemberLink { id: number; targetUrl: Url; - logoType: number; + logoType: LogoType; } export interface Positions { id: number; From c4552e84033b4a56f83f3698844b1f58b43badcb Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:20:40 +0300 Subject: [PATCH 04/26] add using of LOGO_ICONS in components --- .../AdminPage/TeamPage/TeamLink.component.tsx | 13 +++-------- .../TeamModal/TeamModal.component.tsx | 23 +++++++++++-------- .../AdminPage/TeamPage/TeamPage.component.tsx | 13 +++-------- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/features/AdminPage/TeamPage/TeamLink.component.tsx b/src/features/AdminPage/TeamPage/TeamLink.component.tsx index 51726d6ef..1c4eca3e4 100644 --- a/src/features/AdminPage/TeamPage/TeamLink.component.tsx +++ b/src/features/AdminPage/TeamPage/TeamLink.component.tsx @@ -1,18 +1,11 @@ import React from 'react'; -import behance from '@assets/images/partners/behance.svg'; -import facebook from '@assets/images/partners/facebook.svg'; -import http from '@assets/images/partners/http.svg'; -import instagram from '@assets/images/partners/instagram.svg'; -import linkedin from '@assets/images/partners/linkedin.svg'; -import tiktok from '@assets/images/partners/tiktok.svg'; -import twitter from '@assets/images/partners/twitterNew.svg'; -import youtube from '@assets/images/partners/youtube.svg'; import { TeamMemberLinkCreateUpdate } from '@/models/team/team.model'; -const LogoType = [twitter, instagram, facebook, youtube, linkedin, tiktok, behance, http]; +import LOGO_ICONS from './TeamModal/constants/logoIcons'; + const TeamLink: React.FC<{ link: TeamMemberLinkCreateUpdate }> = ({ link }) => { - const LogoComponent = LogoType[link.logoType]; + const LogoComponent = LOGO_ICONS.find( logo => logo.type === link.logoType)!.icon; return ( { const url = formValues.url as string; - const logotype = teamLinksForm.getFieldValue('logotype').split('.')[0]; + // const logotype = teamLinksForm.getFieldValue('logotype').split('.')[0]; + const socialName = teamLinksForm.getFieldValue('logotype'); + const logotype = SOCIAL_OPTIONS.find( opt => opt.value === socialName)?.logo; setExistWarningVisible(false); setCustomWarningVisible(false); setInvalidWarningVisible(false); - if(!url){ + if (!url) { + return; + } + if (logotype === undefined) { return; } - if(!URL.canParse(url)){ + if (!URL.canParse(url)) { setInvalidWarningVisible(true); return; } - if (!url.toLocaleLowerCase().includes(logotype)) { + if (!url.toLocaleLowerCase().includes(socialName)) { setCustomWarningVisible(true); } else { const newId = getNewId(teamSourceLinks); - const isLogoTypePresent = teamSourceLinks.some(obj => obj.logoType === Number(LogoType[logotype])); + const isLogoTypePresent = teamSourceLinks.some(obj => obj.logoType === logotype); - if(isLogoTypePresent){ + if (isLogoTypePresent) { setExistWarningVisible(true); - } - else { + } else { setTeamSourceLinks([...teamSourceLinks, { id: newId, - logoType: Number(LogoType[logotype]), + logoType: logotype, targetUrl: url, }]); } - } }; diff --git a/src/features/AdminPage/TeamPage/TeamPage.component.tsx b/src/features/AdminPage/TeamPage/TeamPage.component.tsx index 1569f050d..6fbad7c65 100644 --- a/src/features/AdminPage/TeamPage/TeamPage.component.tsx +++ b/src/features/AdminPage/TeamPage/TeamPage.component.tsx @@ -3,14 +3,7 @@ import './TeamPage.styles.scss'; import { observer } from 'mobx-react-lite'; import { useEffect, useState } from 'react'; import { DeleteOutlined, EditOutlined, StarOutlined } from '@ant-design/icons'; -import behance from '@assets/images/partners/behance.svg'; -import facebook from '@assets/images/partners/facebook.svg'; -import http from '@assets/images/partners/http.svg'; -import instagram from '@assets/images/partners/instagram.svg'; -import linkedin from '@assets/images/partners/linkedin.svg'; -import tiktok from '@assets/images/partners/tiktok.svg'; -import twitter from '@assets/images/partners/twitterNew.svg'; -import youtube from '@assets/images/partners/youtube.svg'; + import { Button, Table } from 'antd'; import { ColumnsType } from 'antd/es/table'; @@ -24,11 +17,11 @@ import TeamMember, { TeamMemberLink } from '../../../models/team/team.model'; import PageBar from '../PageBar/PageBar.component'; import TeamModal from './TeamModal/TeamModal.component'; +import LOGO_ICONS from './TeamModal/constants/logoIcons'; const TeamPage = () => { const { teamStore } = useMobx(); const { modalStore } = useModalContext(); - const LogoType = [twitter, instagram, facebook, youtube, linkedin, tiktok, behance, http]; const [modalAddOpened, setModalAddOpened] = useState(false); const [modalEditOpened, setModalEditOpened] = useState(false); const [teamToEdit, setTeamToedit] = useState(); @@ -115,7 +108,7 @@ const TeamPage = () => { render: (links: TeamMemberLink[], team) => (
{links.map((link) => { - const LogoComponent = LogoType[link.logoType]; + const LogoComponent = LOGO_ICONS.find( logo => logo.type === link.logoType)!.icon; return ( Date: Thu, 1 Aug 2024 14:39:32 +0300 Subject: [PATCH 05/26] Update ArtGalleryBlock.component.tsx --- .../components/ArtGallery/ArtGalleryBlock.component.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx b/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx index ae009fc06..3f2ccc3e7 100644 --- a/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx +++ b/src/app/common/components/ArtGallery/ArtGalleryBlock.component.tsx @@ -90,13 +90,14 @@ const ArtGallery = ({ if (streetcodeIdValidAndFetchingRequired()) { secondRender.current = true; if (isFillArtsStore) { - const startingSlide = await fetchAllToDefaultTemplate(getStreetCodeId !== -1 ? getStreetCodeId : parseId); + let currStreetcodeId = getStreetCodeId !== -1 ? getStreetCodeId : parseId; + const startingSlide = await fetchAllToDefaultTemplate(currStreetcodeId); let currentSlide = startingSlide ?? 0; while (currentSlide < MAX_SLIDES_AMOUNT) { try { // eslint-disable-next-line no-await-in-loop - await fetchAllArtSlidesByStreetcodeId(getStreetCodeId !== -1 ? getStreetCodeId : parseId, currentSlide); + await fetchAllArtSlidesByStreetcodeId(currStreetcodeId, currentSlide); currentSlide += amountOfSlides; } catch (error: unknown) { @@ -340,4 +341,4 @@ const ArtGallery = ({ ); }; -export default observer(ArtGallery); \ No newline at end of file +export default observer(ArtGallery); From dec6c5c476e46e64ec3495e1a52e4f201a5f8e96 Mon Sep 17 00:00:00 2001 From: Anastasiia <89141775+Spoilsport0@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:45:25 +0300 Subject: [PATCH 06/26] Update streetcode-art-slide-store.ts --- src/app/stores/streetcode-art-slide-store.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/app/stores/streetcode-art-slide-store.ts b/src/app/stores/streetcode-art-slide-store.ts index 23f37c92d..018fcd4e4 100644 --- a/src/app/stores/streetcode-art-slide-store.ts +++ b/src/app/stores/streetcode-art-slide-store.ts @@ -81,14 +81,13 @@ export default class StreetcodeArtSlideStore { } }; - public fetchAllToDefaultTemplate = async (streetcodeid: number): Promise => { - if (!this.streetcodeWasFetched.includes(streetcodeid)) { - const startingPosition = this.streetcodeArtSlides.length; - const slidesCount = await StreetcodeArtApi.getAllCountByStreetcodeId(streetcodeid) - const placeholders = new Array(slidesCount).fill(bindStreetcodeIdToDefaultSlide(streetcodeid), 0, slidesCount); - this.streetcodeArtSlides.push(...placeholders); - return startingPosition; - } + public fetchAllToDefaultTemplate = async (streetcodeId: number): Promise => { + if (this.streetcodeWasFetched.includes(streetcodeId)) {return;} + const startingPosition = this.streetcodeArtSlides.length; + const slidesCount = await StreetcodeArtApi.getAllCountByStreetcodeId(streetcodeId) + const placeholders = new Array(slidesCount).fill(bindStreetcodeIdToDefaultSlide(streetcodeId), 0, slidesCount); + this.streetcodeArtSlides.push(...placeholders); + return startingPosition; } public fetchAllArtSlidesByStreetcodeId = async (streetcodeid: number, startIndex: number) => { @@ -130,4 +129,4 @@ export default class StreetcodeArtSlideStore { return convertedSlide as unknown as StreetcodeArtSlideCreateUpdate; }); } -} \ No newline at end of file +} From 938416568d15fe7f3cb81086c5b1c92253a7c9ca Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:32:21 +0300 Subject: [PATCH 07/26] fix TeamModal to make it testable --- .../TeamModal/TeamModal.component.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx b/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx index 9e7ec9804..3c0d0d634 100644 --- a/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx +++ b/src/features/AdminPage/TeamPage/TeamModal/TeamModal.component.tsx @@ -19,7 +19,7 @@ import { Checkbox, Form, Input, message, Modal, Popover, Select, UploadFile, } from 'antd'; -import FormItem from 'antd/es/form/FormItem'; + import TextArea from 'antd/es/input/TextArea'; import { Option } from 'antd/es/mentions'; @@ -151,7 +151,6 @@ const TeamModal: React.FC<{ const onSuccesfulSubmitLinks = (formValues: any) => { const url = formValues.url as string; - // const logotype = teamLinksForm.getFieldValue('logotype').split('.')[0]; const socialName = teamLinksForm.getFieldValue('logotype'); const logotype = SOCIAL_OPTIONS.find( opt => opt.value === socialName)?.logo; setExistWarningVisible(false); @@ -165,7 +164,9 @@ const TeamModal: React.FC<{ return; } - if (!URL.canParse(url)) { + try { + const urlObject = new URL(url); + } catch { setInvalidWarningVisible(true); return; } @@ -362,12 +363,13 @@ const TeamModal: React.FC<{ layout="vertical" form={teamLinksForm} onFinish={onSuccesfulSubmitLinks} + data-testid="link-form" >
- - {teamSourceLinks.map((link) => ( + {teamSourceLinks.map((link, index) => (
@@ -380,29 +382,30 @@ const TeamModal: React.FC<{ ))}
- + - From 92b86d2cd10316fdcccc7176a044a0df2933cd45 Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:35:37 +0300 Subject: [PATCH 08/26] Add test Add test that checks if adding social links works --- .../TeamPage/TeamModal/TeamModal.spec.tsx | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/features/AdminPage/TeamPage/TeamModal/TeamModal.spec.tsx diff --git a/src/features/AdminPage/TeamPage/TeamModal/TeamModal.spec.tsx b/src/features/AdminPage/TeamPage/TeamModal/TeamModal.spec.tsx new file mode 100644 index 000000000..f36afcddb --- /dev/null +++ b/src/features/AdminPage/TeamPage/TeamModal/TeamModal.spec.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; + +import '@testing-library/jest-dom'; + +import TeamModal from './TeamModal.component'; + +const mockSetIsModalOpen = jest.fn(); + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); + +jest.mock('@/app/api/team/positions.api', () => ({ + getAll: jest.fn(() => Promise.resolve([])), +})); + +describe('TeamModal', () => { + it('should add link on add button click when input is valid', async () => { + render(); + + const form = screen.getByTestId('link-form'); + const logotypeInput = screen.getByTestId('logotype-select').firstElementChild; + const urlInput = screen.getByTestId('link-input'); + const addButton = screen.getByTestId('add-button'); + + fireEvent.mouseDown(logotypeInput!); + const logotypeOption = screen.getByText('TikTok'); + fireEvent.click(logotypeOption); + fireEvent.change(urlInput, { target: { value: 'https://tiktok.com/@user' } }); + fireEvent.submit(addButton); + + await waitFor(() => { + const item = screen.getByTestId('team-source-list-0'); + expect(item).toBeInTheDocument(); + }); + }); +}); From 555cb305396629ae667531c6d326f3ac8d58366d Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 5 Sep 2024 21:03:41 +0200 Subject: [PATCH 09/26] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 118701c22..da11484d6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -238,8 +238,8 @@ pipeline { sh 'echo ${BRANCH_NAME}' sh "git checkout master" sh 'echo ${BRANCH_NAME}' - sh "git merge release/${env.SEM_VERSION}" - sh "npm version ${env.SEM_VERSION} -m 'Upgrade to %s as part of release'" + sh 'git merge ${BRANCH_NAME}' + sh "npm version 1.0.0 -m 'Upgrade to %s as part of release'" sh "git push origin main" From dda8a4f37dd39538938812d7def151b05ef1c294 Mon Sep 17 00:00:00 2001 From: DDeviak <117632082+DDeviak@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:20:46 +0300 Subject: [PATCH 10/26] fix: Add Cache-Control header to index.html --- public/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/public/index.html b/public/index.html index d8b3a7e4e..3cf1d814d 100644 --- a/public/index.html +++ b/public/index.html @@ -5,6 +5,7 @@ + From f01d800bd6bd28ca656cf4e7b1fd5e6a11b2f2cb Mon Sep 17 00:00:00 2001 From: DDeviak <117632082+DDeviak@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:33:56 +0300 Subject: [PATCH 11/26] fix: Update Cache-Control header in index.html --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 3cf1d814d..de46e77c8 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ - + From 92ea6d79dfed5c3a91a9672b236893cf7c2ebfb6 Mon Sep 17 00:00:00 2001 From: DDeviak <117632082+DDeviak@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:52:15 +0300 Subject: [PATCH 12/26] fix: Update webpack.prod.js to use 'StaleWhileRevalidate' caching strategy for static resources --- config/webpack.prod.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/webpack.prod.js b/config/webpack.prod.js index 31219862d..eb6cabc8a 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -54,7 +54,7 @@ module.exports = { runtimeCaching: [ { urlPattern: /\.(?:js|css)$/, - handler: 'CacheFirst', + handler: 'StaleWhileRevalidate', options: { cacheName: 'static-resources', expiration: { From 38ccd77b13c14748aa28019f43b8bd434a59d30e Mon Sep 17 00:00:00 2001 From: DDeviak <117632082+DDeviak@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:00:55 +0300 Subject: [PATCH 13/26] chore: Remove Cache-Control header from index.html --- public/index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/public/index.html b/public/index.html index de46e77c8..d8b3a7e4e 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,6 @@ - From 991f88f6543a7ff457aaea9f8fe3550191b26c94 Mon Sep 17 00:00:00 2001 From: DDeviak <117632082+DDeviak@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:03:46 +0300 Subject: [PATCH 14/26] fix: Update caching strategy for image and font resources in webpack.prod.js --- config/webpack.prod.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/webpack.prod.js b/config/webpack.prod.js index eb6cabc8a..1a7fcc78c 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -65,7 +65,7 @@ module.exports = { }, { urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, - handler: 'CacheFirst', + handler: 'StaleWhileRevalidate', options: { cacheName: 'image-resources', expiration: { @@ -75,7 +75,7 @@ module.exports = { }, { urlPattern: /\.(?:woff|woff2|ttf|otf)$/, - handler:'CacheFirst', + handler:'StaleWhileRevalidate', options: { cacheName: 'font-resources', expiration: { From 9a5a78c7de39a0bfce637cb53c9f720d6b833db0 Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:01:49 +0300 Subject: [PATCH 15/26] Add networkFirst caching mode for js and css files --- config/webpack.prod.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/webpack.prod.js b/config/webpack.prod.js index 1a7fcc78c..7063db33d 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -54,7 +54,7 @@ module.exports = { runtimeCaching: [ { urlPattern: /\.(?:js|css)$/, - handler: 'StaleWhileRevalidate', + handler: 'NetworkFirst', options: { cacheName: 'static-resources', expiration: { From 129c7beba0dca16073befa7d44c8aff2384c114a Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:51:47 +0300 Subject: [PATCH 16/26] Add component for automatic cache cleaning --- public/env-config.js | 1 + src/app/common/components/withClearCache.tsx | 34 ++++++++++++++++++++ src/index.tsx | 16 +++++---- 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 src/app/common/components/withClearCache.tsx diff --git a/public/env-config.js b/public/env-config.js index 111a97b97..fbd5c3254 100644 --- a/public/env-config.js +++ b/public/env-config.js @@ -3,4 +3,5 @@ window._env_ = { API_URL: "https://stageback.streetcode.com.ua/api", REACT_APP_GOOGLE_ANALYTICS: "REACT_APP_GOOGLE_ANALYTICS_VALUE", RECAPTCHA_SITE_KEY: "6LeUO3ApAAAAAOC7F4v0qTsSwIR9mZu33SWjAAtM", + VERSION: "1.0.0" } diff --git a/src/app/common/components/withClearCache.tsx b/src/app/common/components/withClearCache.tsx new file mode 100644 index 000000000..7b4aa9252 --- /dev/null +++ b/src/app/common/components/withClearCache.tsx @@ -0,0 +1,34 @@ +/* eslint-disable no-underscore-dangle */ +import { Component, useEffect, useState } from 'react'; + +const WithClearCache: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [isLatestBuildDate, setIsLatestBuildDate] = useState(false); + + const refreshCacheAndReload = () => { + if (caches) { + caches.keys().then((names) => { + for (const name of names) { + caches.delete(name); + } + }); + } + window.location.reload(); + }; + + useEffect(() => { + const localVersion = localStorage.getItem('VERSION'); + const isVersionMatches = localVersion === window._env_.VERSION; + setIsLatestBuildDate(isVersionMatches); + if (!isVersionMatches) { + localStorage.setItem('VERSION', window._env_.VERSION); + refreshCacheAndReload(); + } + }, []); + + if (isLatestBuildDate) { + return children; + } + return null; +}; + +export default WithClearCache; diff --git a/src/index.tsx b/src/index.tsx index c3bf711c2..a1524593b 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,6 +8,7 @@ import { RouterProvider } from 'react-router-dom'; import router from '@app/router/Routes'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import WithClearCache from './app/common/components/withClearCache'; declare global { interface Window { @@ -16,6 +17,7 @@ declare global { SERVER_API_URL: string; REACT_APP_GOOGLE_ANALYTICS: string; RECAPTCHA_SITE_KEY: string; + VERSION: string; }; } } @@ -39,10 +41,12 @@ const root = ReactDOM.createRoot( const queryClient = new QueryClient(); root.render( - - - - - - , + + + + + + + + , ); From 6b26a3ff6ece3dbc6364e3ccffc9b25a85636359 Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:32:15 +0300 Subject: [PATCH 17/26] set NetworkOnly caching strategy for env-config.js --- config/webpack.dev.js | 107 ++++++++++--------- config/webpack.prod.js | 4 + src/app/common/components/withClearCache.tsx | 1 + 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/config/webpack.dev.js b/config/webpack.dev.js index 972ea2752..a2a4f3e4c 100644 --- a/config/webpack.dev.js +++ b/config/webpack.dev.js @@ -1,4 +1,5 @@ const Dotenv = require("dotenv-webpack"); +const CopyPlugin = require('copy-webpack-plugin'); const Webpack = require("webpack"); const { GenerateSW } = require("workbox-webpack-plugin"); const fs = require("fs"); @@ -13,12 +14,12 @@ module.exports = { open: true, port: "3000", historyApiFallback: true, - // https: { + https: { // DEV.NOTE: uncomment and change names of files according to your generated ones - // key: fs.readFileSync("cert\\localhost+1-key.pem"), - // cert: fs.readFileSync("cert\\localhost+1.pem"), - // }, + key: fs.readFileSync("cert\\localhost+1-key.pem"), + cert: fs.readFileSync("cert\\localhost+1.pem"), + }, }, module: { rules: require("./webpack.rules"), @@ -38,53 +39,57 @@ module.exports = { new Dotenv({ path: `./.env`, }), - // new GenerateSW({ - // skipWaiting: true, - // clientsClaim: true, - // maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, - // runtimeCaching: [ - // { - // urlPattern: /\.(?:js|css)$/, - // handler: 'CacheFirst', - // options: { - // cacheName: 'static-resources', - // expiration: { - // maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week - // }, - // }, - // }, - // { - // urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, - // handler: 'CacheFirst', - // options: { - // cacheName: 'image-resources', - // expiration: { - // maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week - // }, - // }, - // }, - // { - // urlPattern: /\.(?:woff|woff2|ttf|otf)$/, - // handler:'CacheFirst', - // options: { - // cacheName: 'font-resources', - // expiration: { - // maxAgeSeconds: 60 * 60 * 24 * 90, // 3 months - // }, - // }, - // }, - // { - // urlPattern: /^https?.*/, - // handler: 'NetworkFirst', - // options: { - // cacheName: 'external-resources', - // expiration: { - // maxEntries: 260 - // }, - // }, - // }, - // ], - // }), + new GenerateSW({ + skipWaiting: true, + clientsClaim: true, + maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, + runtimeCaching: [ + { + urlPattern: /env-config\.js$/, + handler: 'NetworkOnly' + }, + { + urlPattern: /\.(?:js|css)$/, + handler: 'CacheFirst', + options: { + cacheName: 'static-resources', + expiration: { + maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week + }, + }, + }, + { + urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, + handler: 'CacheFirst', + options: { + cacheName: 'image-resources', + expiration: { + maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week + }, + }, + }, + { + urlPattern: /\.(?:woff|woff2|ttf|otf)$/, + handler:'CacheFirst', + options: { + cacheName: 'font-resources', + expiration: { + maxAgeSeconds: 60 * 60 * 24 * 90, // 3 months + }, + }, + }, + { + urlPattern: /^https?.*/, + handler: 'NetworkFirst', + options: { + cacheName: 'external-resources', + expiration: { + maxEntries: 260 + }, + }, + }, + ], + }), ], optimization: { splitChunks: { diff --git a/config/webpack.prod.js b/config/webpack.prod.js index 7063db33d..c39d6c22b 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -52,6 +52,10 @@ module.exports = { clientsClaim: true, maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, runtimeCaching: [ + { + urlPattern: /env-config\.js$/, + handler: 'NetworkOnly' + }, { urlPattern: /\.(?:js|css)$/, handler: 'NetworkFirst', diff --git a/src/app/common/components/withClearCache.tsx b/src/app/common/components/withClearCache.tsx index 7b4aa9252..84f3fe966 100644 --- a/src/app/common/components/withClearCache.tsx +++ b/src/app/common/components/withClearCache.tsx @@ -11,6 +11,7 @@ const WithClearCache: React.FC<{ children: React.ReactNode }> = ({ children }) = caches.delete(name); } }); + console.log("Cache is cleared") } window.location.reload(); }; From d40ae2b544ebc48243683d53aff3618ed3fc38fb Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:33:20 +0300 Subject: [PATCH 18/26] remove old docker-compose from frontend --- docker-compose.yml | 99 ---------------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 7d0eeeb47..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,99 +0,0 @@ -services: - certbot: - restart: always - image: certbot/certbot:latest - volumes: - - /etc/certbot/www/:/var/www/certbot/:rw - - /etc/certbot/conf/:/etc/letsencrypt/:rw - - nginx: - restart: always - image: nginx:latest - ports: - - "80:80" - - "443:443" - environment: - FRONTEND_SERVER_NAME: ${FRONTEND_SERVER_NAME} - BACKEND_SERVER_NAME: ${BACKEND_SERVER_NAME} - volumes: - - ./templates:/etc/nginx/templates - - /etc/certbot/www:/var/www/certbot/:ro - - /etc/certbot/conf:/etc/nginx/ssl/:ro - - - loki: - restart: always - container_name: loki - image: grafana/loki:latest - ports: - - "3100:3100" - command: -config.file=/etc/loki/local-config.yaml - volumes: - - ./loki/config:/etc/loki - - frontend: - restart: always - image: streetcodeua/streetcode_client:${DOCKER_TAG_FRONTEND} - pull_policy: always - expose: - - "80" - healthcheck: - test: curl --fail http://localhost || exit 1 - interval: 30s - timeout: 10s - retries: 5 - environment: - API_URL: ${ENV_API_BACKEND} - REACT_APP_GOOGLE_ANALYTICS: ${ENV_GOOGLE_ANALYTICS} - RECAPTCHA_SITE_KEY: ${RECAPTCHA_SITE_KEY} - logging: - driver: loki - options: - loki-url: "http://localhost:3100/loki/api/v1/push" - - backend: - restart: always - image: streetcodeua/streetcode:${DOCKER_TAG_BACKEND} - pull_policy: always - expose: - - "80" - environment: - STREETCODE_ConnectionStrings__DefaultConnection: ${DB_CONNECTION_STRING} - STREETCODE_Blob__BlobStoreKey: ${BLOB_STORAGE_KEY} - STREETCODE_Blob__BlobStorePath: /mnt/data/ - STREETCODE_Instagram__InstagramID: ${INSTAGRAM_ID} - STREETCODE_Instagram__InstagramToken: ${INSTAGRAM_TOKEN} - STREETCODE_Payment__Token: ${PAYMENT_TOKEN} - STREETCODE_EMAILCONFIGURATION__PASSWORD: ${EMAIL_PASSWORD} - STREETCODE_RECAPTCHA__SECRETKEY: ${RECAPTCHA_SECRET_KEY} - STREETCODE_CORS__AllowedOrigins: ${CORS_ALLOWED_ORIGINS} - STREETCODE_CORS__AllowedHeaders: ${CORS_ALLOWED_HEADERS} - STREETCODE_CORS__AllowedMethods: ${CORS_ALLOWED_METHODS} - STREETCODE_CORS__ExposedHeaders: ${CORS_EXPOSED_HEADERS} - STREETCODE_CORS__PreflightMaxAge: "600" - STREETCODE_IPRATELIMITING__GENERALRULES__0__LIMIT: 500 - ASPNETCORE_ENVIRONMENT: ${SWAGGER_APP_ENVIRONMENT} - volumes: - - type: bind - source: /imagestorage - target: /mnt/data - healthcheck: - test: curl --fail http://localhost/api/partners/getAll || exit 1 - interval: 30s - timeout: 10s - retries: 5 - extra_hosts: - - "host.docker.internal:host-gateway" - logging: - driver: loki - options: - loki-url: "http://localhost:3100/loki/api/v1/push" -volumes: - backend: -networks: - backend: - external: - name: backend - frontend: - external: - name: frontend From 7bec7e9aea3dcb754c2ded05af85a422622aa031 Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:39:08 +0300 Subject: [PATCH 19/26] comment dev certificates --- config/webpack.dev.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/webpack.dev.js b/config/webpack.dev.js index a2a4f3e4c..ea0a709a1 100644 --- a/config/webpack.dev.js +++ b/config/webpack.dev.js @@ -14,12 +14,12 @@ module.exports = { open: true, port: "3000", historyApiFallback: true, - https: { + //https: { // DEV.NOTE: uncomment and change names of files according to your generated ones - key: fs.readFileSync("cert\\localhost+1-key.pem"), - cert: fs.readFileSync("cert\\localhost+1.pem"), - }, + //key: fs.readFileSync("cert\\localhost+1-key.pem"), + //cert: fs.readFileSync("cert\\localhost+1.pem"), + //}, }, module: { rules: require("./webpack.rules"), From d80df3ef8451a7a30d93e52d7b5fb94b442c8991 Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 12 Sep 2024 21:38:41 +0200 Subject: [PATCH 20/26] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index da11484d6..4f5f59123 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -234,12 +234,12 @@ pipeline { } steps { script { - + git branch: 'master', credentialsId: 'test_git_user', url: 'git@github.com:ita-social-projects/StreetCode_Client.git' sh 'echo ${BRANCH_NAME}' sh "git checkout master" sh 'echo ${BRANCH_NAME}' sh 'git merge ${BRANCH_NAME}' - sh "npm version 1.0.0 -m 'Upgrade to %s as part of release'" + sh "npm version ${env.CODE_VERSION} -m 'Upgrade to %s as part of release'" sh "git push origin main" From 945c73979af94929771e3cfce646e6ca66454783 Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 12 Sep 2024 21:56:50 +0200 Subject: [PATCH 21/26] Update Jenkinsfile --- Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4f5f59123..fc87834c9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -57,6 +57,7 @@ pipeline { sh "cat version" vers = readFile(file: 'version').trim() sh "echo ${vers}" + env.vers="${vers}" env.CODE_VERSION = readFile(file: 'version').trim() echo "${env.CODE_VERSION}" SEM_VERSION="${env.CODE_VERSION}" @@ -239,7 +240,7 @@ pipeline { sh "git checkout master" sh 'echo ${BRANCH_NAME}' sh 'git merge ${BRANCH_NAME}' - sh "npm version ${env.CODE_VERSION} -m 'Upgrade to %s as part of release'" + sh "npm version ${env.vers} -m 'Upgrade to %s as part of release'" sh "git push origin main" From 3e2928ab674b1b41bd861284689554ba9065115e Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 12 Sep 2024 22:05:56 +0200 Subject: [PATCH 22/26] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index fc87834c9..98820c653 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -242,7 +242,7 @@ pipeline { sh 'git merge ${BRANCH_NAME}' sh "npm version ${env.vers} -m 'Upgrade to %s as part of release'" - sh "git push origin main" + sh "git push origin master" } } From d53ce2f9cbbfe2fd544e6a51cae4f5380c69b0c2 Mon Sep 17 00:00:00 2001 From: sashapanasiuk5 <51517423+sashapanasiuk5@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:08:15 +0300 Subject: [PATCH 23/26] Revert "Feature/issue cache control" --- config/webpack.dev.js | 107 +++++++++---------- config/webpack.prod.js | 4 - docker-compose.yml | 99 +++++++++++++++++ public/env-config.js | 1 - src/app/common/components/withClearCache.tsx | 35 ------ src/index.tsx | 16 ++- 6 files changed, 156 insertions(+), 106 deletions(-) create mode 100644 docker-compose.yml delete mode 100644 src/app/common/components/withClearCache.tsx diff --git a/config/webpack.dev.js b/config/webpack.dev.js index ea0a709a1..972ea2752 100644 --- a/config/webpack.dev.js +++ b/config/webpack.dev.js @@ -1,5 +1,4 @@ const Dotenv = require("dotenv-webpack"); -const CopyPlugin = require('copy-webpack-plugin'); const Webpack = require("webpack"); const { GenerateSW } = require("workbox-webpack-plugin"); const fs = require("fs"); @@ -14,12 +13,12 @@ module.exports = { open: true, port: "3000", historyApiFallback: true, - //https: { + // https: { // DEV.NOTE: uncomment and change names of files according to your generated ones - //key: fs.readFileSync("cert\\localhost+1-key.pem"), - //cert: fs.readFileSync("cert\\localhost+1.pem"), - //}, + // key: fs.readFileSync("cert\\localhost+1-key.pem"), + // cert: fs.readFileSync("cert\\localhost+1.pem"), + // }, }, module: { rules: require("./webpack.rules"), @@ -39,57 +38,53 @@ module.exports = { new Dotenv({ path: `./.env`, }), - new GenerateSW({ - skipWaiting: true, - clientsClaim: true, - maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, - runtimeCaching: [ - { - urlPattern: /env-config\.js$/, - handler: 'NetworkOnly' - }, - { - urlPattern: /\.(?:js|css)$/, - handler: 'CacheFirst', - options: { - cacheName: 'static-resources', - expiration: { - maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week - }, - }, - }, - { - urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, - handler: 'CacheFirst', - options: { - cacheName: 'image-resources', - expiration: { - maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week - }, - }, - }, - { - urlPattern: /\.(?:woff|woff2|ttf|otf)$/, - handler:'CacheFirst', - options: { - cacheName: 'font-resources', - expiration: { - maxAgeSeconds: 60 * 60 * 24 * 90, // 3 months - }, - }, - }, - { - urlPattern: /^https?.*/, - handler: 'NetworkFirst', - options: { - cacheName: 'external-resources', - expiration: { - maxEntries: 260 - }, - }, - }, - ], - }), + // new GenerateSW({ + // skipWaiting: true, + // clientsClaim: true, + // maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, + // runtimeCaching: [ + // { + // urlPattern: /\.(?:js|css)$/, + // handler: 'CacheFirst', + // options: { + // cacheName: 'static-resources', + // expiration: { + // maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week + // }, + // }, + // }, + // { + // urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, + // handler: 'CacheFirst', + // options: { + // cacheName: 'image-resources', + // expiration: { + // maxAgeSeconds: 60 * 60 * 24 * 7, // 1 week + // }, + // }, + // }, + // { + // urlPattern: /\.(?:woff|woff2|ttf|otf)$/, + // handler:'CacheFirst', + // options: { + // cacheName: 'font-resources', + // expiration: { + // maxAgeSeconds: 60 * 60 * 24 * 90, // 3 months + // }, + // }, + // }, + // { + // urlPattern: /^https?.*/, + // handler: 'NetworkFirst', + // options: { + // cacheName: 'external-resources', + // expiration: { + // maxEntries: 260 + // }, + // }, + // }, + // ], + // }), ], optimization: { splitChunks: { diff --git a/config/webpack.prod.js b/config/webpack.prod.js index c39d6c22b..7063db33d 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -52,10 +52,6 @@ module.exports = { clientsClaim: true, maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, runtimeCaching: [ - { - urlPattern: /env-config\.js$/, - handler: 'NetworkOnly' - }, { urlPattern: /\.(?:js|css)$/, handler: 'NetworkFirst', diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..7d0eeeb47 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,99 @@ +services: + certbot: + restart: always + image: certbot/certbot:latest + volumes: + - /etc/certbot/www/:/var/www/certbot/:rw + - /etc/certbot/conf/:/etc/letsencrypt/:rw + + nginx: + restart: always + image: nginx:latest + ports: + - "80:80" + - "443:443" + environment: + FRONTEND_SERVER_NAME: ${FRONTEND_SERVER_NAME} + BACKEND_SERVER_NAME: ${BACKEND_SERVER_NAME} + volumes: + - ./templates:/etc/nginx/templates + - /etc/certbot/www:/var/www/certbot/:ro + - /etc/certbot/conf:/etc/nginx/ssl/:ro + + + loki: + restart: always + container_name: loki + image: grafana/loki:latest + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + volumes: + - ./loki/config:/etc/loki + + frontend: + restart: always + image: streetcodeua/streetcode_client:${DOCKER_TAG_FRONTEND} + pull_policy: always + expose: + - "80" + healthcheck: + test: curl --fail http://localhost || exit 1 + interval: 30s + timeout: 10s + retries: 5 + environment: + API_URL: ${ENV_API_BACKEND} + REACT_APP_GOOGLE_ANALYTICS: ${ENV_GOOGLE_ANALYTICS} + RECAPTCHA_SITE_KEY: ${RECAPTCHA_SITE_KEY} + logging: + driver: loki + options: + loki-url: "http://localhost:3100/loki/api/v1/push" + + backend: + restart: always + image: streetcodeua/streetcode:${DOCKER_TAG_BACKEND} + pull_policy: always + expose: + - "80" + environment: + STREETCODE_ConnectionStrings__DefaultConnection: ${DB_CONNECTION_STRING} + STREETCODE_Blob__BlobStoreKey: ${BLOB_STORAGE_KEY} + STREETCODE_Blob__BlobStorePath: /mnt/data/ + STREETCODE_Instagram__InstagramID: ${INSTAGRAM_ID} + STREETCODE_Instagram__InstagramToken: ${INSTAGRAM_TOKEN} + STREETCODE_Payment__Token: ${PAYMENT_TOKEN} + STREETCODE_EMAILCONFIGURATION__PASSWORD: ${EMAIL_PASSWORD} + STREETCODE_RECAPTCHA__SECRETKEY: ${RECAPTCHA_SECRET_KEY} + STREETCODE_CORS__AllowedOrigins: ${CORS_ALLOWED_ORIGINS} + STREETCODE_CORS__AllowedHeaders: ${CORS_ALLOWED_HEADERS} + STREETCODE_CORS__AllowedMethods: ${CORS_ALLOWED_METHODS} + STREETCODE_CORS__ExposedHeaders: ${CORS_EXPOSED_HEADERS} + STREETCODE_CORS__PreflightMaxAge: "600" + STREETCODE_IPRATELIMITING__GENERALRULES__0__LIMIT: 500 + ASPNETCORE_ENVIRONMENT: ${SWAGGER_APP_ENVIRONMENT} + volumes: + - type: bind + source: /imagestorage + target: /mnt/data + healthcheck: + test: curl --fail http://localhost/api/partners/getAll || exit 1 + interval: 30s + timeout: 10s + retries: 5 + extra_hosts: + - "host.docker.internal:host-gateway" + logging: + driver: loki + options: + loki-url: "http://localhost:3100/loki/api/v1/push" +volumes: + backend: +networks: + backend: + external: + name: backend + frontend: + external: + name: frontend diff --git a/public/env-config.js b/public/env-config.js index fbd5c3254..111a97b97 100644 --- a/public/env-config.js +++ b/public/env-config.js @@ -3,5 +3,4 @@ window._env_ = { API_URL: "https://stageback.streetcode.com.ua/api", REACT_APP_GOOGLE_ANALYTICS: "REACT_APP_GOOGLE_ANALYTICS_VALUE", RECAPTCHA_SITE_KEY: "6LeUO3ApAAAAAOC7F4v0qTsSwIR9mZu33SWjAAtM", - VERSION: "1.0.0" } diff --git a/src/app/common/components/withClearCache.tsx b/src/app/common/components/withClearCache.tsx deleted file mode 100644 index 84f3fe966..000000000 --- a/src/app/common/components/withClearCache.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -import { Component, useEffect, useState } from 'react'; - -const WithClearCache: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [isLatestBuildDate, setIsLatestBuildDate] = useState(false); - - const refreshCacheAndReload = () => { - if (caches) { - caches.keys().then((names) => { - for (const name of names) { - caches.delete(name); - } - }); - console.log("Cache is cleared") - } - window.location.reload(); - }; - - useEffect(() => { - const localVersion = localStorage.getItem('VERSION'); - const isVersionMatches = localVersion === window._env_.VERSION; - setIsLatestBuildDate(isVersionMatches); - if (!isVersionMatches) { - localStorage.setItem('VERSION', window._env_.VERSION); - refreshCacheAndReload(); - } - }, []); - - if (isLatestBuildDate) { - return children; - } - return null; -}; - -export default WithClearCache; diff --git a/src/index.tsx b/src/index.tsx index a1524593b..c3bf711c2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,7 +8,6 @@ import { RouterProvider } from 'react-router-dom'; import router from '@app/router/Routes'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; -import WithClearCache from './app/common/components/withClearCache'; declare global { interface Window { @@ -17,7 +16,6 @@ declare global { SERVER_API_URL: string; REACT_APP_GOOGLE_ANALYTICS: string; RECAPTCHA_SITE_KEY: string; - VERSION: string; }; } } @@ -41,12 +39,10 @@ const root = ReactDOM.createRoot( const queryClient = new QueryClient(); root.render( - - - - - - - - , + + + + + + , ); From 703920ef5e261992b211e4269cd51b0e5eede28d Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 12 Sep 2024 22:32:45 +0200 Subject: [PATCH 24/26] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 98820c653..86857b204 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -249,7 +249,7 @@ pipeline { post { success { sh 'gh auth status' - sh "gh release create v${vers} --generate-notes --draft" + sh "gh release create v${vers} --generate-notes --draft --no-git-tag-version" } } From 626e914319c8211d27892233c7124d5ad4298141 Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 12 Sep 2024 22:36:20 +0200 Subject: [PATCH 25/26] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 86857b204..5624c171d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -240,7 +240,7 @@ pipeline { sh "git checkout master" sh 'echo ${BRANCH_NAME}' sh 'git merge ${BRANCH_NAME}' - sh "npm version ${env.vers} -m 'Upgrade to %s as part of release'" + sh "npm version ${env.vers} -m 'Upgrade to %s as part of release' --allow-same-version --no-git-tag-version" sh "git push origin master" @@ -249,7 +249,7 @@ pipeline { post { success { sh 'gh auth status' - sh "gh release create v${vers} --generate-notes --draft --no-git-tag-version" + sh "gh release create v${vers} --generate-notes --draft" } } From 283d01e8424001490c227db838d965580c59935e Mon Sep 17 00:00:00 2001 From: streetcodeUa Date: Thu, 12 Sep 2024 22:42:30 +0200 Subject: [PATCH 26/26] Update Jenkinsfile --- Jenkinsfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5624c171d..dbb63a6bd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -240,8 +240,9 @@ pipeline { sh "git checkout master" sh 'echo ${BRANCH_NAME}' sh 'git merge ${BRANCH_NAME}' - sh "npm version ${env.vers} -m 'Upgrade to %s as part of release' --allow-same-version --no-git-tag-version" - + sh "npm version ${env.vers} --allow-same-version --no-git-tag-version" + sh "git add ." + sh "git commit -m 'Upgrade to %s as part of release'" sh "git push origin master" }