mirror of https://gitee.com/answerdev/answer.git
feat: personal setting notification change
This commit is contained in:
parent
41f7b1b9cd
commit
80df5193c5
|
@ -962,9 +962,16 @@ ui:
|
||||||
placeholder: "City, Country"
|
placeholder: "City, Country"
|
||||||
notification:
|
notification:
|
||||||
heading: Notifications
|
heading: Notifications
|
||||||
email:
|
email: Email
|
||||||
label: Email Notifications
|
inbox:
|
||||||
radio: "Answers to your questions, comments, and more"
|
label: Inbox notifications
|
||||||
|
description: Answers to your questions, comments, invites, and more.
|
||||||
|
all_new_question:
|
||||||
|
label: All new questions
|
||||||
|
description: Get notified of all new questions. Up to 50 questions per week.
|
||||||
|
all_new_question_for_following_tags:
|
||||||
|
label: All new questions for following tags
|
||||||
|
description: Get notified of new questions for following tags.
|
||||||
account:
|
account:
|
||||||
heading: Account
|
heading: Account
|
||||||
change_email_btn: Change email
|
change_email_btn: Change email
|
||||||
|
|
|
@ -57,7 +57,7 @@ export interface TagInfo extends TagBase {
|
||||||
main_tag_slug_name?: string;
|
main_tag_slug_name?: string;
|
||||||
excerpt?;
|
excerpt?;
|
||||||
}
|
}
|
||||||
export interface QuestionParams extends ImgCodeReq{
|
export interface QuestionParams extends ImgCodeReq {
|
||||||
title: string;
|
title: string;
|
||||||
url_title?: string;
|
url_title?: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
@ -589,3 +589,13 @@ export interface UserOauthConnectorItem {
|
||||||
binding: boolean;
|
binding: boolean;
|
||||||
external_id: string;
|
external_id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NotificationConfigItem {
|
||||||
|
enable: boolean;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
export interface NotificationConfig {
|
||||||
|
all_new_question: NotificationConfigItem[];
|
||||||
|
all_new_question_for_following_tags: NotificationConfigItem[];
|
||||||
|
inbox: NotificationConfigItem[];
|
||||||
|
}
|
||||||
|
|
|
@ -27,12 +27,13 @@ const Index: FC<Props> = ({
|
||||||
index: number,
|
index: number,
|
||||||
) => {
|
) => {
|
||||||
const { name, checked } = evt.currentTarget;
|
const { name, checked } = evt.currentTarget;
|
||||||
const freshVal = checked ? enumValues?.[index] : '';
|
enumValues[index] = checked;
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
...formData,
|
...formData,
|
||||||
[name]: {
|
[name]: {
|
||||||
...formData[name],
|
...formData[name],
|
||||||
value: freshVal,
|
value: enumValues,
|
||||||
isInvalid: false,
|
isInvalid: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -51,7 +52,7 @@ const Index: FC<Props> = ({
|
||||||
name={fieldName}
|
name={fieldName}
|
||||||
id={`form-${String(item)}`}
|
id={`form-${String(item)}`}
|
||||||
label={enumNames?.[index]}
|
label={enumNames?.[index]}
|
||||||
checked={(fieldObject?.value || '') === item}
|
checked={fieldObject?.value?.[index] || false}
|
||||||
feedback={fieldObject?.errorMsg}
|
feedback={fieldObject?.errorMsg}
|
||||||
feedbackType="invalid"
|
feedbackType="invalid"
|
||||||
isInvalid={fieldObject?.isInvalid}
|
isInvalid={fieldObject?.isInvalid}
|
||||||
|
|
|
@ -386,8 +386,13 @@ export const initFormData = (schema: JSONSchema): Type.FormDataType => {
|
||||||
const props: JSONSchema['properties'] = schema?.properties || {};
|
const props: JSONSchema['properties'] = schema?.properties || {};
|
||||||
Object.keys(props).forEach((key) => {
|
Object.keys(props).forEach((key) => {
|
||||||
const prop = props[key];
|
const prop = props[key];
|
||||||
const defaultVal = prop?.default;
|
let defaultVal: any = '';
|
||||||
|
if (Array.isArray(prop.default) && prop.enum && prop.enum.length > 0) {
|
||||||
|
// for checkbox default values
|
||||||
|
defaultVal = prop.enum;
|
||||||
|
} else {
|
||||||
|
defaultVal = prop?.default;
|
||||||
|
}
|
||||||
formData[key] = {
|
formData[key] = {
|
||||||
value: defaultVal,
|
value: defaultVal,
|
||||||
isInvalid: false,
|
isInvalid: false,
|
||||||
|
|
|
@ -30,7 +30,7 @@ export interface JSONSchema {
|
||||||
description?: string;
|
description?: string;
|
||||||
enum?: Array<string | boolean | number>;
|
enum?: Array<string | boolean | number>;
|
||||||
enumNames?: string[];
|
enumNames?: string[];
|
||||||
default?: string | boolean | number;
|
default?: string | boolean | number | any[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { usePageTags } from '@/hooks';
|
import { usePageTags } from '@/hooks';
|
||||||
import * as Type from '@/common/interface';
|
import * as Type from '@/common/interface';
|
||||||
import { FollowingTags, CustomSidebar } from '@/components';
|
import { FollowingTags, CustomSidebar, Icon } from '@/components';
|
||||||
import {
|
import {
|
||||||
useTagInfo,
|
useTagInfo,
|
||||||
useFollow,
|
useFollow,
|
||||||
|
@ -141,9 +141,16 @@ const Index: FC = () => {
|
||||||
|
|
||||||
<div className="box-ft">
|
<div className="box-ft">
|
||||||
{tagInfo.is_follower ? (
|
{tagInfo.is_follower ? (
|
||||||
<Button variant="primary" onClick={() => toggleFollow()}>
|
<div>
|
||||||
{t('button_following')}
|
<Button variant="primary" onClick={() => toggleFollow()}>
|
||||||
</Button>
|
{t('button_following')}
|
||||||
|
</Button>
|
||||||
|
<Link
|
||||||
|
className="btn btn-outline-secondary ms-2"
|
||||||
|
to="/users/settings/notify">
|
||||||
|
<Icon name="bell-fill" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
variant="outline-primary"
|
variant="outline-primary"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useState, FormEvent, useEffect } from 'react';
|
import React, { useState, FormEvent, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { FormDataType } from '@/common/interface';
|
import type { FormDataType, NotificationConfig } from '@/common/interface';
|
||||||
import { useToast } from '@/hooks';
|
import { useToast } from '@/hooks';
|
||||||
import { setNotice, getLoggedUserInfo } from '@/services';
|
import { useGetNotificationConfig, putNotificationConfig } from '@/services';
|
||||||
import { SchemaForm, JSONSchema, UISchema, initFormData } from '@/components';
|
import { SchemaForm, JSONSchema, UISchema, initFormData } from '@/components';
|
||||||
|
|
||||||
const Index = () => {
|
const Index = () => {
|
||||||
|
@ -11,46 +11,90 @@ const Index = () => {
|
||||||
const { t } = useTranslation('translation', {
|
const { t } = useTranslation('translation', {
|
||||||
keyPrefix: 'settings.notification',
|
keyPrefix: 'settings.notification',
|
||||||
});
|
});
|
||||||
|
const { data: configData } = useGetNotificationConfig();
|
||||||
|
|
||||||
const schema: JSONSchema = {
|
const schema: JSONSchema = {
|
||||||
title: t('heading'),
|
title: t('heading'),
|
||||||
properties: {
|
properties: {
|
||||||
notice_switch: {
|
inbox: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
title: t('email.label'),
|
title: t('inbox.label'),
|
||||||
default: false,
|
description: t('inbox.description'),
|
||||||
|
enum: configData?.inbox?.map((v) => v.enable),
|
||||||
|
default: configData?.inbox?.map((v) => v.enable),
|
||||||
|
enumNames: configData?.inbox?.map((v) => t(v.key)),
|
||||||
|
},
|
||||||
|
all_new_question: {
|
||||||
|
type: 'boolean',
|
||||||
|
title: t('all_new_question.label'),
|
||||||
|
description: t('all_new_question.description'),
|
||||||
|
enum: configData?.all_new_question?.map((v) => v.enable),
|
||||||
|
default: configData?.all_new_question?.map((v) => v.enable),
|
||||||
|
enumNames: configData?.all_new_question?.map((v) => t(v.key)),
|
||||||
|
},
|
||||||
|
all_new_question_for_following_tags: {
|
||||||
|
type: 'boolean',
|
||||||
|
title: t('all_new_question_for_following_tags.label'),
|
||||||
|
description: t('all_new_question_for_following_tags.description'),
|
||||||
|
enum: configData?.all_new_question_for_following_tags?.map(
|
||||||
|
(v) => v.enable,
|
||||||
|
),
|
||||||
|
default: configData?.all_new_question_for_following_tags?.map(
|
||||||
|
(v) => v.enable,
|
||||||
|
),
|
||||||
|
enumNames: configData?.all_new_question_for_following_tags?.map((v) =>
|
||||||
|
t(v.key),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const uiSchema: UISchema = {
|
const uiSchema: UISchema = {
|
||||||
notice_switch: {
|
inbox: {
|
||||||
'ui:widget': 'switch',
|
'ui:widget': 'checkbox',
|
||||||
'ui:options': {
|
'ui:options': {
|
||||||
label: t('email.radio'),
|
label: t('email'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
all_new_question: {
|
||||||
|
'ui:widget': 'checkbox',
|
||||||
|
'ui:options': {
|
||||||
|
label: t('email'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
all_new_question_for_following_tags: {
|
||||||
|
'ui:widget': 'checkbox',
|
||||||
|
'ui:options': {
|
||||||
|
label: t('email'),
|
||||||
|
text: t('all_new_question_for_following_tags.description'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const [formData, setFormData] = useState<FormDataType>(initFormData(schema));
|
const [formData, setFormData] = useState<FormDataType>(initFormData(schema));
|
||||||
|
|
||||||
const getProfile = () => {
|
useEffect(() => {
|
||||||
getLoggedUserInfo().then((res) => {
|
setFormData(initFormData(schema));
|
||||||
if (res) {
|
}, [configData]);
|
||||||
setFormData({
|
|
||||||
notice_switch: {
|
|
||||||
value: res.notice_status === 1,
|
|
||||||
isInvalid: false,
|
|
||||||
errorMsg: '',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = (event: FormEvent) => {
|
const handleSubmit = (event: FormEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
setNotice({
|
const params = {
|
||||||
notice_switch: formData.notice_switch.value,
|
inbox: configData?.inbox.map((v, index) => {
|
||||||
}).then(() => {
|
return { enable: formData.inbox.value[index], key: v.key };
|
||||||
|
}),
|
||||||
|
all_new_question: configData?.all_new_question.map((v, index) => {
|
||||||
|
return { enable: formData.all_new_question.value[index], key: v.key };
|
||||||
|
}),
|
||||||
|
all_new_question_for_following_tags:
|
||||||
|
configData?.all_new_question_for_following_tags.map((v, index) => {
|
||||||
|
return {
|
||||||
|
enable: formData.all_new_question_for_following_tags.value[index],
|
||||||
|
key: v.key,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
} as NotificationConfig;
|
||||||
|
|
||||||
|
putNotificationConfig(params).then(() => {
|
||||||
toast.onShow({
|
toast.onShow({
|
||||||
msg: t('update', { keyPrefix: 'toast' }),
|
msg: t('update', { keyPrefix: 'toast' }),
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
|
@ -58,9 +102,6 @@ const Index = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getProfile();
|
|
||||||
}, []);
|
|
||||||
const handleChange = (ud) => {
|
const handleChange = (ud) => {
|
||||||
setFormData(ud);
|
setFormData(ud);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import type * as Type from '@/common/interface';
|
import type * as Type from '@/common/interface';
|
||||||
|
|
||||||
|
@ -14,3 +16,14 @@ export const updateUserInterface = (lang: string) => {
|
||||||
language: lang,
|
language: lang,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetNotificationConfig = () => {
|
||||||
|
return useSWR<Type.NotificationConfig>(
|
||||||
|
'/answer/api/v1/user/notification/config',
|
||||||
|
request.instance.get,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const putNotificationConfig = (data: Type.NotificationConfig) => {
|
||||||
|
return request.put('/answer/api/v1/user/notification/config', data);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue