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

feat: use custom component for time of day setting #53

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
08e5a8f
add api endpoint to run legal hold job on demand
mickmister May 8, 2024
4bfa0fe
fix lint
mickmister May 9, 2024
07793ac
PR feedback
mickmister May 9, 2024
0fac0cb
call job in goroutine to avoid blocking ServeHTTP hook
mickmister May 9, 2024
bc19ac0
reorder defer blocks for cleaning up legal hold job
mickmister May 15, 2024
54aa700
call context cancel function in defer
mickmister May 15, 2024
e6e186d
move processAllLegalHolds body back into run() method
mickmister May 15, 2024
f3e4a81
support using a different s3 bucket through plugin setting
mickmister May 19, 2024
a926e08
move code around
mickmister May 21, 2024
1b464d7
update readme
mickmister May 21, 2024
c2708a3
Merge remote-tracking branch 'origin/main' into add-api-endpoint-to-r…
wiggin77 May 21, 2024
568f22b
Merge remote-tracking branch 'origin/main' into separate-s3-bucket
wiggin77 May 21, 2024
507a0b3
Merge branch 'add-api-endpoint-to-run-job' into separate-s3-bucket
mickmister May 22, 2024
eb63d08
initial s3 bucket form implementation
mickmister May 23, 2024
71bd47d
test connection works
mickmister May 23, 2024
930e5bf
show success/fail connection messages. check connection on plugin sta…
mickmister May 23, 2024
997fb1b
update readme
mickmister May 23, 2024
135c267
disable inputs instead of hiding
mickmister May 23, 2024
b19af3a
Added common settings with custom select
fmartingr May 29, 2024
4a09178
Merge remote-tracking branch 'origin/main' into feat/timeofday-custom…
fmartingr Jun 4, 2024
e3680b3
form state save
fmartingr Jun 6, 2024
7537b09
Merge branch 'main' into feat/timeofday-custom-component
mattermost-build Sep 27, 2024
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
8 changes: 3 additions & 5 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@
"footer": "",
"settings": [
{
"key": "TimeOfDay",
"display_name": "Time of day:",
"type": "text",
"help_text": "Time of day to run the Legal Hold task, in the form 'HH:MM ±HHMM' (e.g. '3:00am -0700'). Use +0000 for UTC.",
"default": "1:00am -0700"
"key": "CommonSettings",
"display_name": "Common Settings:",
"type": "custom"
},
{
"key": "LegalHoldsSettings",
Expand Down
39 changes: 39 additions & 0 deletions webapp/src/components/admin_console_settings/select_setting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';

import BaseSetting from './base_setting';

Check failure on line 3 in webapp/src/components/admin_console_settings/select_setting.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be at least one empty line between import groups
import ReactSelect, { ActionMeta } from 'react-select';

Check failure on line 4 in webapp/src/components/admin_console_settings/select_setting.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

`react-select` import should occur before import of `./base_setting`

Check failure on line 4 in webapp/src/components/admin_console_settings/select_setting.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space after '{'

Check failure on line 4 in webapp/src/components/admin_console_settings/select_setting.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space before '}'

export type OptionType = {
label: string | JSX.Element;
value: string;
}

type Props = {
id: string;
name: string;
helpText: string;
onChange: (value: OptionType) => void;
value: OptionType;
getOptions: () => OptionType[];
disabled?: boolean;
};

const SelectSetting = (props: Props) => {
return (
<BaseSetting
{...props}
>
<ReactSelect
id={props.id}
onChange={props.onChange}
isDisabled={props.disabled}
value={props.value}
hideSelectedOptions={true}
isSearchable={true}
options={props.getOptions()}
/>
</BaseSetting>
);
};

export default SelectSetting;
85 changes: 85 additions & 0 deletions webapp/src/components/common_settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { useEffect, useMemo, useState } from 'react';

Check failure on line 1 in webapp/src/components/common_settings.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space after '{'

Check failure on line 1 in webapp/src/components/common_settings.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space before '}'

import { IntlProvider } from 'react-intl';

Check failure on line 3 in webapp/src/components/common_settings.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space after '{'

Check failure on line 3 in webapp/src/components/common_settings.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space before '}'

import SelectSetting, { OptionType } from './admin_console_settings/select_setting';

Check failure on line 5 in webapp/src/components/common_settings.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be at least one empty line between import groups

Check failure on line 5 in webapp/src/components/common_settings.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

There should be no space after '{'
import { func } from 'prop-types';

type CommonSettingsData = {
TimeOfDay: OptionType;
};

const useCommonSettingsForm = (initialValue: CommonSettingsData | undefined, onChange: (id: string, value: CommonSettingsData) => void) => {
const [formState, setFormState] = useState<CommonSettingsData>({
TimeOfDay: initialValue?.TimeOfDay ?? { label: '12:00am', value: '00:00' },
});

return useMemo(() => ({
formState,
setFormValue: <T extends keyof CommonSettingsData>(key: T, value: CommonSettingsData[T]) => {
const newState = {
...formState,
[key]: value,
};

setFormState(newState);
onChange('PluginSettings.Plugins.com+mattermost+plugin-legal-hold.commonsettings', newState);
},
}), [formState, setFormState, onChange]);
};

type Props = {
value: CommonSettingsData | undefined;
onChange: (id: string, value: CommonSettingsData) => void;
};

const getJobTimeOptions = () => {
const options: OptionType[] = [];
return () => {
if (options.length > 0) {
return options;
}
const minuteIntervals = ['00', '15', '30', '45'];
for (let h = 0; h < 24; h++) {
let hourLabel = h;
let hourValue = `${h}`;
const timeOfDay = h >= 12 ? 'pm' : 'am';
if (hourLabel < 10) {
hourValue = `0${hourValue}`;
}
if (hourLabel > 12) {
hourLabel -= 12;
}
if (hourLabel === 0) {
hourLabel = 12;
}
for (let i = 0; i < minuteIntervals.length; i++) {
options.push({
label: `${hourLabel}:${minuteIntervals[i]}${timeOfDay}`,
value: `${hourValue}:${minuteIntervals[i]}`
});
}
}

return options;
};
};

const CommonSettings = (props: Props) => {
const { formState, setFormValue } = useCommonSettingsForm(props.value, props.onChange);

return (
<IntlProvider locale='en-US'>
<SelectSetting
id={'com.mattermost.plugin-legal-hold.TimeOfDay'}
name={'Time of day'}
helpText={'Time of day to run the Legal Hold task'}
value={formState.TimeOfDay}
onChange={(value) => setFormValue('TimeOfDay', value)}
getOptions={getJobTimeOptions()}
/>
</IntlProvider>
);
};

export default CommonSettings;
2 changes: 2 additions & 0 deletions webapp/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {manifest} from '@/manifest';
import {PluginRegistry} from '@/types/mattermost-webapp';
import LegalHoldsSetting from '@/components/legal_holds_setting';
import AmazonS3BucketSettings from '@/components/amazon_s3_bucket_settings';
import CommonSettings from '@/components/common_settings';

export default class Plugin {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
public async initialize(registry: PluginRegistry, store: Store<GlobalState, Action<Record<string, unknown>>>) {
// @see https://developers.mattermost.com/extend/plugins/webapp/reference/
registry.registerAdminConsoleCustomSetting('CommonSettings', CommonSettings, {showTitle: false});
registry.registerAdminConsoleCustomSetting('LegalHoldsSettings', LegalHoldsSetting, {showTitle: false});
registry.registerAdminConsoleCustomSetting('AmazonS3BucketSettings', AmazonS3BucketSettings, {showTitle: false});
}
Expand Down
Loading