Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sub-menu(description): implemented change description #120

Merged
merged 5 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- Change Image(sub menu) functionality added for active apps
- App overview 'in review' style fix
- Enhance Sub Menu by adding 'Change Description' for active apps
- Change Description(sub menu) functionality added for active apps
- Bugfix
- Service Release Process
- Service Release process not working
Expand Down
15 changes: 14 additions & 1 deletion src/assets/locales/de/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,18 @@
"successMsg": "successfully changed app lead image",
"errorMsg": "Unable to change the lead image"
},
"changeDescription": {
"headerTitle": "Change Descriptions",
"description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard .Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard .",
"longDescription": "Long Description",
"longDescriptionEN": "Long Description - EN *",
"longDescriptionDE": "Long Description - DE *",
"shortDescription": "Short Description",
"shortDescriptionEN": "Short Description - EN *",
"shortDescriptionDE": "Short Description - DE *",
"successMsg": "successfully changed description",
"errorMsg": "Unable to change description"
},
"appreleaseprocess": {
"message": "App Release Process Message"
},
Expand Down Expand Up @@ -1048,7 +1060,8 @@
},
"dataSavedSuccessMessage": "Data saved successfully",
"errormessage": "Error! Something went wrong",
"fileSizeError": "Uploaded file is too big. Maximum 0.8MB is allowed"
"fileSizeError": "Uploaded file is too big. Maximum 0.8MB is allowed",
"shouldNotStartWith": "and should not start with"
},
"footerButtons": {
"help": "Help",
Expand Down
15 changes: 14 additions & 1 deletion src/assets/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,18 @@
"successMsg": "successfully changed app lead image",
"errorMsg": "Unable to change the lead image"
},
"changeDescription": {
"headerTitle": "Change Descriptions",
"description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard .Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard .",
"longDescription": "Long Description",
"longDescriptionEN": "Long Description - EN *",
"longDescriptionDE": "Long Description - DE *",
"shortDescription": "Short Description",
"shortDescriptionEN": "Short Description - EN *",
"shortDescriptionDE": "Short Description - DE *",
"successMsg": "successfully changed description",
"errorMsg": "Unable to change description"
},
"appreleaseprocess": {
"message": "App Release Process Message"
},
Expand Down Expand Up @@ -1010,7 +1022,8 @@
},
"dataSavedSuccessMessage": "Data saved successfully",
"errormessage": "Error! Something went wrong",
"fileSizeError": "Uploaded file is too big. Maximum 0.8MB is allowed"
"fileSizeError": "Uploaded file is too big. Maximum 0.8MB is allowed",
"shouldNotStartWith": "and should not start with"
},
"footerButtons": {
"help": "Help",
Expand Down
325 changes: 324 additions & 1 deletion src/components/pages/AppOverview/ChangeDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,329 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

import { PageBreadcrumb } from 'components/shared/frame/PageBreadcrumb/PageBreadcrumb'
import {
Typography,
PageHeader,
Button,
LoadingButton,
TabPanel,
} from '@catena-x/portal-shared-components'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
import { Box, IconButton, Tab, Tabs } from '@mui/material'
import { useEffect, useMemo, useState } from 'react'
import { error, success } from 'services/NotifyService'
import ConnectorFormInputFieldShortAndLongDescription from 'components/shared/basic/ReleaseProcess/components/ConnectorFormInputFieldShortAndLongDescription'
import Patterns from 'types/Patterns'
import { useForm } from 'react-hook-form'
import {
useFetchDescriptionQuery,
useSaveDescriptionMutation,
} from 'features/appManagement/apiSlice'
import HelpOutlineIcon from '@mui/icons-material/HelpOutline'
import TextSnippetOutlinedIcon from '@mui/icons-material/TextSnippetOutlined'

export default function ChangeDescription() {
return <>In Progress</>
const { t } = useTranslation()
const navigate = useNavigate()
const appId = useParams().appId
const [isLoading, setIsLoading] = useState(false)
const { state } = useLocation()
const items: any = state
const app = items?.filter((item: any) => item.id === appId)
const [activeTab, setActiveTab] = useState<number>(0)
const longDescriptionMaxLength = 2000
const { data: description, refetch } = useFetchDescriptionQuery(appId ?? '')
const [saveDescription] = useSaveDescriptionMutation()

const defaultValues = useMemo(() => {
return {
longDescriptionEN: description?.[0].longDescription ?? '',
longDescriptionDE: description?.[1].longDescription ?? '',
shortDescriptionEN: description?.[0].shortDescription ?? '',
shortDescriptionDE: description?.[1].shortDescription ?? '',
}
}, [description])

useEffect(() => {
refetch()
reset(defaultValues)
}, [state, description])

const {
handleSubmit,
control,
trigger,
formState: { errors, isDirty, isValid },
getValues,
reset,
} = useForm({
defaultValues: defaultValues,
mode: 'onChange',
})

const handleSave = async (data: any) => {
setIsLoading(true)

if (appId) {
const saveData = {
appId: appId,
body: [
{
languageCode: 'de',
longDescription: getValues().longDescriptionDE,
shortDescription: getValues().shortDescriptionDE,
},
{
languageCode: 'en',
longDescription: getValues().longDescriptionEN,
shortDescription: getValues().shortDescriptionEN,
},
],
}

await saveDescription(saveData)
.unwrap()
.then(() => {
navigate('/appoverview', {
state: 'change-description-success',
})
success(t('content.changeDescription.successMsg'))
})
.catch((err) => {
setIsLoading(false)
error(t('content.changeDescription.errorMsg'), '', err)
})
}
}

const patternValidation = (item: string) => {
if (
(item === 'longDescriptionEN' &&
/[ @=<>*\-+#?%&_:;]/.test(getValues().longDescriptionEN?.charAt(0))) ||
item === 'longDescriptionEN'
) {
return `${t(
'content.apprelease.appReleaseForm.validCharactersIncludes'
)} a-zA-Z0-9 !?@&#'"()[]_-+=<>/*.,;:% ${t(
'content.apprelease.appReleaseForm.shouldNotStartWith'
)} @=<>*-+ #?%&_:;`
} else {
return `${t(
'content.apprelease.appReleaseForm.validCharactersIncludes'
)} a-zA-ZÀ-ÿ0-9 !?@&#'"()[]_-+=<>/*.,;:% ${t(
'content.apprelease.appReleaseForm.shouldNotStartWith'
)} @=<>*-+ #?%&_:;`
}
}

return (
<main className="change-image-main">
<PageHeader title={app?.[0]?.title} headerHeight={200} topPage={true}>
<PageBreadcrumb backButtonVariant="contained" />
</PageHeader>
<section>
<Typography variant="body2" align="center" mb={3}>
{app?.[0]?.title}
</Typography>
<Typography variant="h2" align="center" mb={3}>
{t('content.changeDescription.headerTitle')}
</Typography>
<Typography variant="body2" align="center">
{t('content.changeDescription.description')}
</Typography>
</section>
<div className="main-container">
<div className="main-row">
<Tabs
value={activeTab}
onChange={(e, newValue: number) => setActiveTab(newValue)}
centered
sx={{
'.MuiTab-root': {
textTransform: 'none',
},
}}
>
<Tab
sx={{
fontSize: '16px',
'&.Mui-selected': {
borderBottom: '3px solid #0f71cb',
},
}}
label={t('content.changeDescription.longDescription')}
icon={<TextSnippetOutlinedIcon />}
id={`simple-tab-${activeTab}`}
aria-controls={`simple-tabpanel-${activeTab}`}
iconPosition="start"
/>
<Tab
sx={{
fontSize: '16px',
'&.Mui-selected': {
borderBottom: '3px solid #0f71cb',
},
}}
label={t('content.changeDescription.shortDescription')}
icon={<TextSnippetOutlinedIcon />}
id={`simple-tab-${activeTab}`}
aria-controls={`simple-tabpanel-${activeTab}`}
iconPosition="start"
/>
</Tabs>

<TabPanel value={activeTab} index={0}>
<div className="form-field">
{['longDescriptionEN', 'longDescriptionDE'].map(
(item: string) => (
<div key={item}>
<ConnectorFormInputFieldShortAndLongDescription
{...{
control,
trigger,
errors,
item,
}}
label={
<>
{item === 'longDescriptionEN'
? t('content.changeDescription.longDescriptionEN')
: t('content.changeDescription.longDescriptionDE')}
<IconButton sx={{ color: '#939393' }} size="small">
<HelpOutlineIcon />
</IconButton>
</>
}
value={
(item === 'longDescriptionEN'
? getValues().longDescriptionEN?.length
: getValues().longDescriptionDE?.length) +
`/${longDescriptionMaxLength}`
}
patternKey="longDescriptionEN"
patternEN={Patterns.appPage.longDescriptionEN}
patternDE={Patterns.appPage.longDescriptionDE}
rules={{
required:
t(`content.apprelease.appPage.${item}`) +
t('content.apprelease.appReleaseForm.isMandatory'),
minLength: `${t(
'content.apprelease.appReleaseForm.minimum'
)} 10 ${t(
'content.apprelease.appReleaseForm.charactersRequired'
)}`,
pattern: patternValidation(item),
maxLength: `${t(
'content.apprelease.appReleaseForm.maximum'
)} ${longDescriptionMaxLength} ${t(
'content.apprelease.appReleaseForm.charactersAllowed'
)}`,
}}
maxLength={longDescriptionMaxLength}
/>
</div>
)
)}
</div>
</TabPanel>
<TabPanel value={activeTab} index={1}>
<div className="form-field">
{['shortDescriptionEN', 'shortDescriptionDE'].map(
(item: string, i) => (
<div key={item}>
<ConnectorFormInputFieldShortAndLongDescription
{...{
control,
trigger,
errors,
item,
}}
label={
<>
{item === 'shortDescriptionEN'
? t('content.changeDescription.shortDescriptionEN')
: t('content.changeDescription.shortDescriptionDE')}
<IconButton sx={{ color: '#939393' }} size="small">
<HelpOutlineIcon />
</IconButton>
</>
}
value={
(item === 'shortDescriptionEN'
? getValues().shortDescriptionEN?.length
: getValues().shortDescriptionDE?.length) + '/255'
}
patternDE={Patterns.appMarketCard.shortDescriptionDE}
patternEN={Patterns.appMarketCard.shortDescriptionEN}
patternKey="shortDescriptionEN"
rules={{
required: `${t(
`content.apprelease.appMarketCard.${item}`
)} ${t(
'content.apprelease.appReleaseForm.isMandatory'
)}`,
maxLength: `${t(
'content.apprelease.appReleaseForm.maximum'
)} 255 ${t(
'content.apprelease.appReleaseForm.charactersAllowed'
)}`,
minLength: `${t(
'content.apprelease.appReleaseForm.minimum'
)} 10 ${t(
'content.apprelease.appReleaseForm.charactersRequired'
)}`,
pattern: `${t(
'content.apprelease.appReleaseForm.validCharactersIncludes'
)} ${
item === 'shortDescriptionEN'
? 'a-zA-Z0-9 !?@&#\'"()_-=/*.,;:'
: 'a-zA-ZÀ-ÿ0-9 !?@&#\'"()_-=/*.,;:'
}`,
}}
/>
</div>
)
)}
</div>
</TabPanel>
</div>
</div>
<section>
<hr style={{ border: 0, borderTop: '1px solid #DCDCDC' }} />
<Box sx={{ position: 'relative', marginTop: '30px' }}>
<Button
color="secondary"
onClick={() => navigate('/appoverview')}
size="small"
>
{t('global.actions.cancel')}
</Button>

<span style={{ position: 'absolute', right: '10px' }}>
{isLoading ? (
<LoadingButton
size="small"
variant="contained"
onButtonClick={() => {}}
loading={isLoading}
label={`${t('global.actions.confirm')}`}
loadIndicator="Loading..."
/>
) : (
<Button
disabled={!(isDirty && isValid)}
size="small"
variant="contained"
onClick={handleSubmit((data) => handleSave(data))}
>
{t('global.actions.save')}
</Button>
)}
</span>
</Box>
</section>
</main>
)
}
Loading