Skip to content

Commit

Permalink
Merge branch 'notifications-on-keywords' into 'master'
Browse files Browse the repository at this point in the history
custom keywords notifications in params for desktop

See merge request kchat/webapp!930
  • Loading branch information
antonbuks committed Sep 30, 2024
2 parents 491652e + 7d66b45 commit 0e4f649
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import debounce from 'lodash/debounce';
import type {RefObject} from 'react';
import React from 'react';
import {FormattedMessage} from 'react-intl';
import type {ValueType} from 'react-select';
import ReactSelect from 'react-select';
import CreatableSelect from 'react-select/creatable';
import semver from 'semver';

import type {PreferenceType} from '@mattermost/types/preferences';
Expand All @@ -21,15 +23,25 @@ import type {ActionResult} from 'mattermost-redux/types/actions';
import Toggle from 'components/toggle';

import Constants, {NotificationLevels, Preferences} from 'utils/constants';
import {t} from 'utils/i18n';
import {isDesktopApp} from 'utils/user_agent';
import {localizeMessage, moveCursorToEnd} from 'utils/utils';

import DesktopNotificationSettings from './desktop_notification_setting/desktop_notification_settings';

import RhsSettingsItem from '../rhs_settings_item/rhs_settings_item';

import './rhs_settings_notifications.scss';

import DesktopNotificationSettings from './desktop_notification_setting/desktop_notification_settings';
type InputProps ={
display: string;
description: {
id: string;
message: string;
};
title: {
id: string;
message: string;
};
}
export type Props = {
user: UserProfile;
updateSection: (section: string) => void;
Expand Down Expand Up @@ -64,6 +76,9 @@ type State = {
isSaving: boolean;
serverError: string;
emailInterval: number;
keywordsValues: Array<{ label: string; value: string }>;
inputValue: string;
showSelect: boolean;
};

function getNotificationsStateFromProps(props: Props, state?: State): State {
Expand Down Expand Up @@ -177,6 +192,9 @@ function getNotificationsStateFromProps(props: Props, state?: State): State {
notifyCommentsLevel: comments,
isSaving: false,
serverError: '',
keywordsValues: state?.keywordsValues || [],
inputValue: state?.inputValue || '',
showSelect: state?.showSelect || false,
emailInterval: props.emailInterval,
};
}
Expand Down Expand Up @@ -212,6 +230,16 @@ export default class RhsNotificationsTab extends React.PureComponent<Props, Stat
this.handleMentionKeysInput.flush();
}

componentDidMount(): void {
const {user} = this.props;
const keywords = user.notify_props.mention_keys || null;
const keywordsArray = keywords ? keywords.split(',').map((keyword) => this.createOption(keyword)) : [];
this.setState({
keywordsValues: keywordsArray,
showSelect: keywordsArray.length > 0,
});
}

handleSubmit = (): void => {
const data: UserNotifyProps = {} as UserNotifyProps;
data.email = this.state.enableEmail;
Expand All @@ -236,19 +264,9 @@ export default class RhsNotificationsTab extends React.PureComponent<Props, Stat
);
}

const mentionKeys = [];
if (this.state.usernameKey) {
mentionKeys.push(this.props.user.username);
}

let stringKeys = mentionKeys.join(',');
if (this.state.customKeys.length > 0 && this.state.customKeysChecked) {
stringKeys += ',' + this.state.customKeys;
}

data.mention_keys = stringKeys;
data.first_name = this.state.firstNameKey.toString() as UserNotifyProps['first_name'];
data.channel = this.state.channelKey.toString() as UserNotifyProps['channel'];
data.mention_keys = (this.state.keywordsValues || []).map((keyword: { value: string }) => keyword.value).join(',');

this.setState({isSaving: true});

Expand Down Expand Up @@ -348,6 +366,156 @@ export default class RhsNotificationsTab extends React.PureComponent<Props, Stat
);
};

createOption = (label: string) => ({
label,
value: label.toLowerCase().replace(/\W/g, ''),
});

createInput(props: InputProps) {
const {
display,
description,
title,
} = props;

const messageTitle = (
<FormattedMessage
id={title.id}
defaultMessage={title.message}
/>
);

const messageDesc = (
<FormattedMessage
id={description.id}
defaultMessage={description.message}
/>
);

const helpMessage = (
<FormattedMessage
id={'user.settings.display.keywords_help'}
defaultMessage={'Press Tab or use commas to separate keywords.'}
/>
);

const placeholderMessage = (
<FormattedMessage
id={'user.settings.display.keywords_placeholder'}
defaultMessage={'Keywords'}
/>
);

const handleKeyDown = (event: React.KeyboardEvent) => {
if (!this.state.inputValue) {
return;
}

const newKeywords = this.state.inputValue.split(',').map((keyword: string) => this.createOption(keyword.trim()));

switch (event.key) {
case 'Enter':
case 'Tab':
this.setState((prevState) => ({
keywordsValues: Array.isArray(prevState.keywordsValues) ? [...prevState.keywordsValues, ...newKeywords] : newKeywords,
inputValue: '',
}), () => {
this.handleSubmit();
});
event.preventDefault();
break;
default:
break;
}
};

const handleOnChange = (newValues: ValueType<{ label: string; value: string }>) => {
const valuesArray = Array.isArray(newValues) ? newValues : [];
this.setState({keywordsValues: valuesArray}, () => {
this.handleSubmit();
});
};

const toggleSelectVisibility = () => {
this.setState((prevState) => {
const newShowSelect = !prevState.showSelect;
const newKeywordsValues = newShowSelect ? prevState.keywordsValues : [];

return {
showSelect: newShowSelect,
keywordsValues: newKeywordsValues,
inputValue: newShowSelect ? prevState.inputValue : '',
};
}, async () => {
if (!this.state.showSelect) {
this.handleSubmit();
}
});
};

const handleInputChange = (inputValue: string) => {
this.setState({inputValue});
};

const handleBlur = () => {
if (!this.state.inputValue) {
return;
}

const newKeywords = this.state.inputValue.split(',').map((keyword: string) => this.createOption(keyword.trim()));

this.setState((prevState) => ({
keywordsValues: Array.isArray(prevState.keywordsValues) ? [...prevState.keywordsValues, ...newKeywords] : newKeywords,
inputValue: '',
}), () => {
this.handleSubmit();
});
};

return (
<>
<RhsSettingsItem
key={display}
title={messageTitle}
inputs={
<div>
<div>
<Toggle
onToggle={toggleSelectVisibility}
toggled={this.state.showSelect}
/>
</div>

</div>
}
saving={this.state.isSaving}
messageDesc={messageDesc}
updateSection={this.props.updateSection}
/>
{this.state.showSelect && (
<div className='users-settings'>
<CreatableSelect
isClearable={true}
isMulti={true}
menuIsOpen={false}
onChange={handleOnChange}
onInputChange={handleInputChange}
onKeyDown={handleKeyDown}
value={this.state.keywordsValues}
inputValue={this.state.inputValue}
placeholder={placeholderMessage}
components={{DropdownIndicator: null, IndicatorSeparator: null}}
onBlur={handleBlur}
/>
<div className='settings-desc help-keyword'>
{helpMessage}
</div>
</div>
)}
</>
);
}

createPushNotificationSection = () => {
const options = [
{
Expand Down Expand Up @@ -748,6 +916,18 @@ export default class RhsNotificationsTab extends React.PureComponent<Props, Stat
}, DEBOUNCE_DELAY);

render() {
const keywordsSection = this.createInput({
display: 'keywordDisplay',
title: {
id: t('user.settings.display.keywords'),
message: 'Receive notifications for certain keywords',
},
description: {
id: t('user.settings.display.keywords_desc'),
message: 'Keywords are case insensitive.',
},
});

return (
<div id='notificationSettings'>
<div className='user-settings user-rhs-container container mt-0'>
Expand Down Expand Up @@ -792,6 +972,8 @@ export default class RhsNotificationsTab extends React.PureComponent<Props, Stat
</h5>
<div className='divider-dark mt-5 rhs-custom-bb'/>
{this.createEmailNotificationSection()}
<div className='divider-dark mt-5 rhs-custom-bb'/>
{keywordsSection}
</div>
</div>

Expand Down
4 changes: 4 additions & 0 deletions webapp/channels/src/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -5682,6 +5682,10 @@
"user.settings.display.fixedWidthCentered": "Feste Breite, zentriert",
"user.settings.display.fullScreen": "Ganze Breite",
"user.settings.display.icon": "Anzeigeeinstellungen-Symbol",
"user.settings.display.keywords": "Benachrichtigungen für bestimmte Schlüsselwörter erhalten",
"user.settings.display.keywords_desc": "Schlüsselwörter sind nicht case-sensitiv.",
"user.settings.display.keywords_help": "Drücken Sie Tab oder verwenden Sie Kommas, um Schlüsselwörter zu trennen.",
"user.settings.display.keywords_placeholder": "Schlüsselwörter",
"user.settings.display.language": "Sprache",
"user.settings.display.lastActiveDesc": "Wenn aktiviert, können andere Benutzer sehen, wann du zuletzt aktiv warst.",
"user.settings.display.lastActiveDisplay": "Zuletzt Aktiv teilen",
Expand Down
4 changes: 4 additions & 0 deletions webapp/channels/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5699,6 +5699,10 @@
"user.settings.display.fixedWidthCentered": "Fixed width, centered",
"user.settings.display.fullScreen": "Full width",
"user.settings.display.icon": "Display Settings Icon",
"user.settings.display.keywords": "Receive notifications for certain keywords",
"user.settings.display.keywords_desc": "Keywords are case insensitive.",
"user.settings.display.keywords_help": "Press Tab or use commas to separate keywords.",
"user.settings.display.keywords_placeholder": "Keywords",
"user.settings.display.language": "Language",
"user.settings.display.lastActiveDesc": "When enabled, other users will see when you were last active.",
"user.settings.display.lastActiveDisplay": "Share last active time",
Expand Down
4 changes: 4 additions & 0 deletions webapp/channels/src/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -4676,6 +4676,10 @@
"user.settings.display.fixedWidthCentered": "De ancho fijo, centrado",
"user.settings.display.fullScreen": "De ancho total",
"user.settings.display.icon": "Icono de Configuración de Visualización",
"user.settings.display.keywords": "Recibir notificaciones para ciertas palabras clave",
"user.settings.display.keywords_desc": "Las palabras clave no distinguen entre mayúsculas y minúsculas.",
"user.settings.display.keywords_help": "Presione Tab o use comas para separar las palabras clave.",
"user.settings.display.keywords_placeholder": "Palabras clave",
"user.settings.display.language": "Idioma",
"user.settings.display.lastActiveOff": "Apagar",
"user.settings.display.lastActiveOn": "Encender",
Expand Down
4 changes: 4 additions & 0 deletions webapp/channels/src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -4607,6 +4607,10 @@
"user.settings.display.fixedWidthCentered": "Largeur fixe, centré",
"user.settings.display.fullScreen": "Largeur pleine",
"user.settings.display.icon": "Icône de paramètres d'affichage",
"user.settings.display.keywords": "Recevoir des notifications pour certains mots-clés",
"user.settings.display.keywords_desc": "Les mots-clés sont non sensibles à la casse.",
"user.settings.display.keywords_help": "Appuyez sur Tab ou utilisez des virgules pour séparer les mots-clés.",
"user.settings.display.keywords_placeholder": "Mots-clés",
"user.settings.display.language": "Langue",
"user.settings.display.linkPreviewDesc": "Lorsque disponible, le premier lien web du message affichera un aperçu du contenu du site web en dessous du message.",
"user.settings.display.linkPreviewDisplay": "Aperçus des liens de site web",
Expand Down
4 changes: 4 additions & 0 deletions webapp/channels/src/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -3513,6 +3513,10 @@
"user.settings.display.fixedWidthCentered": "Larghezza fissa, centrato",
"user.settings.display.fullScreen": "A tutta larghezza",
"user.settings.display.icon": "Icona Impostazioni aspetto",
"user.settings.display.keywords": "Ricevi notifiche per determinate parole chiave",
"user.settings.display.keywords_desc": "Le parole chiave non sono sensibili alle maiuscole.",
"user.settings.display.keywords_help": "Premi Tab o usa le virgole per separare le parole chiave.",
"user.settings.display.keywords_placeholder": "Parole chiave",
"user.settings.display.language": "Lingua",
"user.settings.display.linkPreviewDesc": "Se disponibile, il primo collegamento web in un messaggio visualizzerà un'anteprima del contenuto del sito sotto il messaggio.",
"user.settings.display.linkPreviewDisplay": "Anteprima siti web",
Expand Down
7 changes: 6 additions & 1 deletion webapp/channels/src/sass/routes/_settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@

.settings-desc {
font-size: 12px;
color: rgba(var(--center-channel-color-rgb),0.785)
color: rgba(var(--center-channel-color-rgb),0.785);

&.help-keyword {
padding-top: 15px;
padding-bottom: 15px;
}
}
.title-select {
display: flex;
Expand Down

0 comments on commit 0e4f649

Please sign in to comment.