office-ui-fabric-react#DefaultButton TypeScript Examples
The following examples show how to use
office-ui-fabric-react#DefaultButton.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LoadProgress.tsx From NetworkViewPCF with MIT License | 6 votes |
render() {
const { progressText, isLoading, cancelRequested, isPaused } = this.props.vm;
return (
<>
<Transition in={isLoading || isPaused} timeout={500} classNames="my-node">
{state =>
state != "exited" && (
<Stack style={progressBoxStyle} className={this.getTransitionClass(state)}>
<Stack.Item>{progressText}</Stack.Item>
{isLoading && (
<Stack.Item>
{!cancelRequested && <DefaultButton text="Cancel" onClick={this.onCancel}></DefaultButton>}
</Stack.Item>
)}
{isPaused && (
<Stack.Item>
{!cancelRequested && <DefaultButton text="Resume" onClick={this.onResume}></DefaultButton>}
</Stack.Item>
)}
</Stack>
)
}
</Transition>
</>
);
}
Example #2
Source File: SpfxFluentuiMessagebar.tsx From SPFx with Mozilla Public License 2.0 | 6 votes |
public render(): React.ReactElement<ISpfxFluentuiMessagebarProps> {
return (
<div className={styles.spfxFluentuiMessagebar}>
{(this.state.InfoMessage) ? <div><InfoMessage /><br /></div> : ''}
{(this.state.ErrorMessage) ? <div><ErrorMessage /><br /></div> : ''}
{(this.state.AccessMessage) ? <div><AccessMessage /><br /></div> : ''}
{(this.state.WarningMessage) ? <div><WarningMessage /><br /></div> : ''}
{(this.state.SuccessQuestion) ? <div><SuccessQuestion /><br /></div> : ''}
{(this.state.WarningQuestion) ? <div><WarningQuestion /><br /></div> : ''}
{(this.state.WarningLongMessage) ? <div><WarningLongMessage /><br /></div> : ''}
<br />
<br />
<Stack horizontal tokens={stackTokens}>
<PrimaryButton text="Show Info Message" onClick={() => this._showMessageClicked('InfoMessage')} />
<PrimaryButton text="Show Error Message" onClick={() => this._showMessageClicked('ErrorMessage')} />
<PrimaryButton text="Show Access Message" onClick={() => this._showMessageClicked('AccessMessage')} />
</Stack>
<br />
<br />
<Stack horizontal tokens={stackTokens}>
<PrimaryButton text="Show Warning Message" onClick={() => this._showMessageClicked('WarningMessage')} />
<PrimaryButton text="Show Success with Question Message" onClick={() => this._showMessageClicked('SuccessQuestion')} />
<PrimaryButton text="Show Warning with Question Message" onClick={() => this._showMessageClicked('WarningQuestion')} />
</Stack>
<br />
<br />
<Stack horizontal tokens={stackTokens}>
<PrimaryButton text="Show Long Message" onClick={() => this._showMessageClicked('WarningLongMessage')} />
<PrimaryButton text="Show info message and hide after 5 sec" onClick={this._showandhideMessageClicked} />
<DefaultButton text="Hide All Message" onClick={this._hideMessageClicked} />
</Stack>
</div>
);
}
Example #3
Source File: Killjob.tsx From AIPerf with MIT License | 6 votes |
render(): React.ReactNode {
const { isCalloutVisible } = this.state;
const prompString = 'Are you sure to cancel this trial?';
return (
<div>
<div className={styles.buttonArea} ref={(menuButton): any => (this.menuButtonElement = menuButton)}>
<PrimaryButton className="detail-button-operation" onClick={this.openPromot} title="kill">{blocked}</PrimaryButton>
</div>
{isCalloutVisible ? (
<div>
<FocusTrapCallout
role="alertdialog"
className={styles.callout}
gapSpace={0}
target={this.menuButtonElement}
onDismiss={this.onDismiss}
setInitialFocus={true}
>
<div className={styles.header}>
<p className={styles.title}>Kill trial</p>
</div>
<div className={styles.inner}>
<div>
<p className={styles.subtext}>{prompString}</p>
</div>
</div>
<FocusZone>
<Stack className={styles.buttons} gap={8} horizontal>
<DefaultButton onClick={this.onDismiss}>No</DefaultButton>
<PrimaryButton onClick={this.onKill}>Yes</PrimaryButton>
</Stack>
</FocusZone>
</FocusTrapCallout>
</div>
) : null}
</div>
);
}
Example #4
Source File: Confirm.tsx From sp-site-designs-studio with MIT License | 6 votes |
public render(): React.ReactElement<IConfirmBoxProps> {
return (
<DialogContent
title={this.props.title}
subText={this.props.message}
onDismiss={this._onCancel}
showCloseButton={false}
>
<DialogFooter>
<PrimaryButton text={this.props.okLabel} title={this.props.okLabel} onClick={this._onConfirm} />
<DefaultButton
text={this.props.cancelLabel}
title={this.props.cancelLabel}
onClick={this._onCancel}
/>
</DialogFooter>
</DialogContent>
);
}
Example #5
Source File: TagList.tsx From art with MIT License | 6 votes |
render() {
return (
<div className="search__section">
<DefaultButton className="search__button" text="Clear Filters" onClick={this.props.clearActiveFilters} />
{Object.entries(this.props.facets).map((nameFacetEntries:any,) =>
<React.Fragment>
<div className="search__row_category" ><b>{nameFacetEntries[0]}</b></div>
{nameFacetEntries[1].map((facetInfo:any) =>
<div className="search__row" key={facetInfo.value} >
<input
className="search__checkbox"
type="checkbox" id={facetInfo.value}
checked={this.isChecked(this.props.activeFilters, nameFacetEntries[0], facetInfo.value)}
onChange={e => this.onCheckboxChange(e, nameFacetEntries[0], facetInfo.value)} />
<label className="search__label" htmlFor={facetInfo.value}>{facetInfo.value + ` (${facetInfo.count})`}</label>
</div>
)}
</React.Fragment>
)}
</div>
);
}
Example #6
Source File: ChangeColumnComponent.tsx From AIPerf with MIT License | 6 votes |
render(): React.ReactNode {
const { showColumn, isHideDialog } = this.props;
const { userSelectColumnList } = this.state;
const renderOptions: Array<CheckBoxItems> = [];
showColumn.map(item => {
if (userSelectColumnList.includes(item)) {
// selected column name
renderOptions.push({ label: item, checked: true, onChange: this.makeChangeHandler(item) });
} else {
renderOptions.push({ label: item, checked: false, onChange: this.makeChangeHandler(item) });
}
});
return (
<div>
<Dialog
hidden={isHideDialog} // required field!
dialogContentProps={{
type: DialogType.largeHeader,
title: 'Change table column',
subText: 'You can chose which columns you want to see in the table.'
}}
modalProps={{
isBlocking: false,
styles: { main: { maxWidth: 450 } }
}}
>
<div className="columns-height">
{renderOptions.map(item => {
return <Checkbox key={item.label} {...item} styles={{ root: { marginBottom: 8 } }} />
})}
</div>
<DialogFooter>
<PrimaryButton text="Save" onClick={this.saveUserSelectColumn} />
<DefaultButton text="Cancel" onClick={this.cancelOption} />
</DialogFooter>
</Dialog>
</div>
);
}
Example #7
Source File: ErrorPage.tsx From hypertrons-crx with Apache License 2.0 | 5 votes |
ErrorPage: React.FC<ErrorPageProps> = ({ errorCode }) => {
const [inited, setInited] = useState(false);
const [settings, setSettings] = useState(new Settings());
useEffect(() => {
const initSettings = async () => {
const temp = await loadSettings();
setSettings(temp);
setInited(true);
};
if (!inited) {
initSettings();
}
}, [inited, settings]);
const errMessageObj = getMessageByLocale(
`global_error_message_${errorCode}`,
settings.locale
);
const onButtonClick = () => {
history.go(-1);
};
return (
<Stack
tokens={stackTokens}
style={{
width: '250px',
margin: 'auto',
}}
>
<Stack.Item>
<FontIcon iconName="PageRemove" style={{ fontSize: 30 }} />
</Stack.Item>
<Stack.Item>
<h3>{errMessageObj.status}</h3>
</Stack.Item>
<Stack.Item>
<strong>{errMessageObj.measure.text}</strong>
<ul style={{ margin: '15px 0 0 15px' }}>
{errMessageObj.measure.tips.map((tip: string) => {
return <li>{tip}</li>;
})}
</ul>
</Stack.Item>
<Stack.Item>
<Link href={HYPERTRONS_CRX_NEW_ISSUE} target="_blank" underline>
{getMessageByLocale('global_sendFeedback', settings.locale)}
</Link>
</Stack.Item>
<Stack.Item>
<DefaultButton
text={getMessageByLocale('global_btn_goBack', settings.locale)}
iconProps={navigateBackIcon}
onClick={onButtonClick}
/>
</Stack.Item>
</Stack>
);
}
Example #8
Source File: ErrorPage.tsx From msteams-meetings-template with MIT License | 5 votes |
function ErrorPageComponent(props: ErrorPageProps) {
return (
<>
<Header />
<Stack
className="container"
horizontalAlign="center"
verticalAlign="center"
verticalFill
tokens={{
childrenGap: 35
}}
>
<img
className="splashImage"
src={errorImage}
alt={translate('errorPage.splash.altText')}
/>
<Text variant="xLargePlus" styles={boldStyle}>
<FormattedMessage id="errorPage.heading" />
</Text>
<Text variant="medium" className="uTextCenter">
<FormattedMessage id="errorPage.subheading" />
</Text>
<Stack horizontal tokens={{ childrenGap: 10 }}>
<DefaultButton
className="teamsButtonInverted"
onClick={() => props.goBack()}
ariaLabel={translate('errorPage.back.ariaLabel')}
>
<FormattedMessage id="errorPage.back" />
</DefaultButton>
<PrimaryButton
className="teamsButton"
onClick={() => props.retryCreateMeeting(props.meeting)}
ariaLabel={translate('errorPage.try.again')}
>
<FormattedMessage id="errorPage.try.again" />
</PrimaryButton>
</Stack>
</Stack>
</>
);
}
Example #9
Source File: MeetingPage.tsx From msteams-meetings-template with MIT License | 4 votes |
function MeetingPageComponent(props: MeetingPageProps) {
const [validationEnabled, setValidationEnabled] = useState(false);
function onSubjectChanged(
evt: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
newValue: string | undefined
) {
// The meeting objects are small, cloning is cheap enough
// Normally would use immutable records or similar to avoid overhead.
const nextMeeting = _.cloneDeep(props.meeting);
nextMeeting.subject = newValue ?? '';
props.setMeeting(nextMeeting);
}
function onStartDateSelected(date?: Moment) {
const nextMeeting = _.cloneDeep(props.meeting);
nextMeeting.startDateTime = date ?? nextMeeting.startDateTime;
// If start >= end, adjust to be the same delta as before from the start time
if (nextMeeting.startDateTime.isSameOrAfter(nextMeeting.endDateTime)) {
const existingDelta = moment(props.meeting.endDateTime).diff(
moment(props.meeting.startDateTime)
);
const newEndDateTime = moment(nextMeeting.startDateTime).add(
existingDelta
);
if (nextMeeting.startDateTime.isSameOrAfter(newEndDateTime)) {
newEndDateTime.add(existingDelta);
}
nextMeeting.endDateTime = newEndDateTime;
}
props.setMeeting(nextMeeting);
}
function onEndDateSelected(date?: Moment) {
const nextMeeting = _.cloneDeep(props.meeting);
const newEndDateTime = date ?? nextMeeting.endDateTime;
// Allow the change only if it maintains start < end
if (!nextMeeting.startDateTime.isAfter(newEndDateTime)) {
nextMeeting.endDateTime = newEndDateTime;
}
props.setMeeting(nextMeeting);
}
function onCreate() {
if (!!props.validationFailures.invalidTitle) {
setValidationEnabled(true);
return;
}
props.createMeeting(props.meeting);
}
if (props.creationInProgress) {
return (
<div className="spinnerContainer">
<Spinner size={SpinnerSize.large} />
</div>
);
}
return (
<div className="newMeetingContainer">
<Stack
className="container"
verticalFill
tokens={{
childrenGap: 35
}}
>
<Stack horizontal tokens={{ childrenGap: 15 }}>
<StackItem grow>
<FontIcon iconName="Calendar" className={meetingIconClass} />
<Text variant="xLarge" styles={boldStyle}>
<FormattedMessage id="meetingPage.header" />
</Text>
</StackItem>
<StackItem align="end" className="newMeetingButtons">
<Stack horizontal tokens={{ childrenGap: 10 }}>
<PrimaryButton
className="teamsButton"
disabled={props.creationInProgress}
onClick={() => onCreate()}
ariaLabel={translate('meetingPage.create.ariaLabel')}
>
<FormattedMessage id="meetingPage.create" />
</PrimaryButton>
<DefaultButton
className="teamsButtonInverted"
disabled={props.creationInProgress}
onClick={() => props.cancel()}
ariaLabel={translate('meetingPage.cancel.ariaLabel')}
>
<FormattedMessage id="meetingPage.cancel" />
</DefaultButton>
</Stack>
</StackItem>
</Stack>
<Stack horizontal>
<StackItem className="newMeetingInputIcon">
<FontIcon iconName="Edit" className={inputIconClass} />
</StackItem>
<StackItem grow>
<TextField
className="newMeetingInput"
placeholder={translate('meetingPage.title.input')}
value={props.meeting?.subject}
underlined
onChange={onSubjectChanged}
errorMessage={
validationEnabled
? props.validationFailures.invalidTitle
: undefined
}
/>
</StackItem>
</Stack>
<div className="newMeetingDatePickerContainer">
<FontIcon iconName="Clock" className={inputIconClass} />
<div className="newMeetingPicker">
<DateTimePicker
dateTime={props.meeting.startDateTime}
minDate={moment()}
onTimeUpdated={onStartDateSelected}
includeDuration={false}
iconName="ReplyAlt"
/>
<DateTimePicker
dateTime={props.meeting.endDateTime}
minDate={props.meeting.startDateTime}
onTimeUpdated={onEndDateSelected}
includeDuration={true}
/>
</div>
</div>
{/* MOBILE BUTTON GROUP */}
</Stack>
<StackItem className="newMeetingButtonsMobile">
<Stack horizontal tokens={{ childrenGap: 10 }}>
<PrimaryButton
className="teamsButton teamsButtonFullWidth"
disabled={props.creationInProgress}
onClick={() => onCreate()}
ariaLabel={translate('meetingPage.create.ariaLabel')}
>
<FormattedMessage id="meetingPage.create" />
</PrimaryButton>
<DefaultButton
className="teamsButtonInverted teamsButtonFullWidth"
disabled={props.creationInProgress}
onClick={() => props.cancel()}
ariaLabel={translate('meetingPage.cancel.ariaLabel')}
>
<FormattedMessage id="meetingPage.cancel" />
</DefaultButton>
</Stack>
</StackItem>
</div>
);
}
Example #10
Source File: Options.tsx From hypertrons-crx with Apache License 2.0 | 4 votes |
Options: React.FC = () => {
const [settings, setSettings] = useState(new Settings());
const [metaData, setMetaData] = useState(new MetaData());
const [inited, setInited] = useState(false);
const [version, setVersion] = useState('0.0.0');
const [checkingUpdate, setCheckingUpdate] = useState(false);
const [token, setToken] = useState('');
const [checkingToken, setCheckingToken] = useState(false);
const [showDialogToken, setShowDialogToken] = useState(false);
const [showDialogTokenError, setShowDialogTokenError] = useState(false);
const [showDialogNotification, setShowDialogNotification] = useState(false);
const [notificationId, setNotificationId] = useState(0);
const [notification, setNotification] = useState('');
const [updateStatus, setUpdateStatus] = useState(UpdateStatus.undefine);
const [updateUrl, setUpdateUrl] = useState(
'https://github.com/hypertrons/hypertrons-crx/releases'
);
const tokenCurrent = metaData.token;
const graphOptions: IChoiceGroupOption[] = [
{
key: 'antv',
text: 'Antv',
},
{
key: 'echarts',
text: 'Echarts',
},
];
const locale = settings.locale;
const localeOptions: IChoiceGroupOption[] = [
{
key: 'en',
text: 'English',
},
{
key: 'zh_CN',
text: '简体ä¸æ–‡ (Simplified Chinese)',
},
];
useEffect(() => {
const initMetaData = async () => {
const tempMetaData = await loadMetaData();
setMetaData(tempMetaData);
if (tempMetaData.token !== '') {
setToken(tempMetaData.token);
}
const notificationInformation = await getNotificationInformation();
if (
notificationInformation.is_published &&
tempMetaData.idLastNotication < notificationInformation.id
) {
if (locale === 'zh_CN') {
setNotification(notificationInformation.content.zh);
} else {
setNotification(notificationInformation.content.en);
}
setNotificationId(notificationInformation.id);
setShowDialogNotification(true);
}
};
if (!inited) {
initMetaData();
}
}, [inited, locale, metaData]);
useEffect(() => {
const initSettings = async () => {
const temp = await loadSettings();
setSettings(temp);
setInited(true);
};
if (!inited) {
initSettings();
}
}, [inited, settings]);
const getVersion = async () => {
let version = (await chrome.management.getSelf()).version;
setVersion(version);
};
useEffect(() => {
getVersion();
}, [version]);
const saveSettings = async (settings: Settings) => {
setSettings(settings);
await chromeSet('settings', settings.toJson());
};
const checkUpdateManually = async () => {
setUpdateStatus(UpdateStatus.undefine);
setCheckingUpdate(true);
const [currentVersion, latestVersion, updateUrl] = await checkUpdate();
if (compareVersion(currentVersion, latestVersion) === -1) {
setUpdateUrl(updateUrl);
setUpdateStatus(UpdateStatus.yes);
} else {
setUpdateStatus(UpdateStatus.no);
}
setCheckingUpdate(false);
};
if (!inited) {
return <div />;
}
return (
<Stack>
{showDialogNotification && (
<Dialog
hidden={!showDialogNotification}
onDismiss={() => {
setShowDialogNotification(false);
}}
dialogContentProps={{
type: DialogType.normal,
title: getMessageByLocale(
'global_notificationTitle',
settings.locale
),
}}
modalProps={{
isBlocking: true,
}}
>
<Text variant="mediumPlus">{notification}</Text>
<DialogFooter>
<DefaultButton
onClick={() => {
setShowDialogNotification(false);
}}
>
{getMessageByLocale('global_btn_ok', settings.locale)}
</DefaultButton>
<PrimaryButton
onClick={async () => {
metaData.idLastNotication = notificationId;
setMetaData(metaData);
await chromeSet('meta_data', metaData.toJson());
setShowDialogNotification(false);
}}
>
{getMessageByLocale('global_btn_disable', settings.locale)}
</PrimaryButton>
</DialogFooter>
</Dialog>
)}
{showDialogToken && (
<Dialog
hidden={!showDialogToken}
onDismiss={() => {
setShowDialogToken(false);
}}
dialogContentProps={{
type: DialogType.normal,
title: getMessageByLocale(
'options_token_dialog_title',
settings.locale
),
}}
modalProps={{
isBlocking: true,
}}
>
<p style={{ fontSize: 14, color: '#6a737d', margin: 5 }}>
{getMessageByLocale(
'options_token_dialog_description',
settings.locale
)}
</p>
<Stack horizontal style={{ fontSize: 16, margin: 5 }}>
<Link
href="https://github.com/settings/tokens/new"
target="_blank"
underline
>
{getMessageByLocale(
'options_token_dialog_message',
settings.locale
)}
</Link>
</Stack>
{checkingToken && (
<Spinner
label={getMessageByLocale(
'options_token_dialog_checking',
settings.locale
)}
/>
)}
{showDialogTokenError && (
<MessageBar messageBarType={MessageBarType.error}>
{getMessageByLocale(
'options_token_dialog_error',
settings.locale
)}
</MessageBar>
)}
<Stack
horizontal
horizontalAlign="space-around"
verticalAlign="end"
style={{ margin: '10px' }}
tokens={{
childrenGap: 15,
}}
>
<TextField
style={{ width: '200px' }}
defaultValue={token}
onChange={(e, value) => {
if (value) {
setShowDialogTokenError(false);
setToken(value);
}
}}
/>
<PrimaryButton
disabled={checkingToken}
onClick={async () => {
setCheckingToken(true);
const result = await checkIsTokenAvailabe(token);
setCheckingToken(false);
if ('id' in result) {
metaData.token = token;
metaData.avatar = result['avatar_url'];
metaData.name = result['name'];
metaData.id = result['id'];
setMetaData(metaData);
await chromeSet('meta_data', metaData.toJson());
setShowDialogToken(false);
} else {
setShowDialogTokenError(true);
}
}}
>
{getMessageByLocale('global_btn_ok', settings.locale)}
</PrimaryButton>
</Stack>
{tokenCurrent !== '' && (
<DefaultButton
onClick={async () => {
metaData.token = '';
metaData.avatar = '';
metaData.name = '';
metaData.id = '';
setMetaData(metaData);
await chromeSet('meta_data', metaData.toJson());
setShowDialogToken(false);
}}
style={{
width: 120,
}}
>
{getMessageByLocale('options_token_btn_rmToken', settings.locale)}
</DefaultButton>
)}
</Dialog>
)}
<Stack horizontalAlign="center" style={{ paddingBottom: '10px' }}>
<h1>PERCEPTOR</h1>
<sub>{`version ${version}`}</sub>
</Stack>
<Stack
horizontalAlign="center"
tokens={{
childrenGap: 30,
}}
>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_enable_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale('options_enable_title', settings.locale)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack
style={{ margin: '10px 25px' }}
tokens={{
childrenGap: 10,
}}
>
<p>
{getMessageByLocale('options_enable_toolTip', settings.locale)}.
</p>
<Toggle
label={getMessageByLocale(
'options_enable_toggle_autoCheck',
settings.locale
)}
defaultChecked={settings.isEnabled}
onText={getMessageByLocale(
'global_toggle_onText',
settings.locale
)}
offText={getMessageByLocale(
'global_toggle_offText',
settings.locale
)}
onChange={async (e, checked) => {
settings.isEnabled = checked;
await saveSettings(settings);
}}
/>
</Stack>
</Stack.Item>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_locale_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale('options_locale_title', settings.locale)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack style={{ margin: '10px 25px' }}>
<p>
{getMessageByLocale('options_locale_toolTip', settings.locale)} :
</p>
<ChoiceGroup
defaultSelectedKey={settings.locale}
options={localeOptions}
onChange={async (e, option: any) => {
settings.locale = option.key;
await saveSettings(settings);
}}
/>
</Stack>
</Stack.Item>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_components_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale(
'options_components_title',
settings.locale
)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack
style={{ margin: '10px 25px' }}
tokens={{
childrenGap: 10,
}}
>
<p>
{getMessageByLocale(
'options_components_toolTip',
settings.locale
)}{' '}
:
</p>
<Checkbox
label={getMessageByLocale(
'component_developerCollabrationNetwork_title',
settings.locale
)}
defaultChecked={settings.developerNetwork}
onChange={async (e, checked) => {
settings.developerNetwork = checked;
await saveSettings(settings);
}}
/>
<Checkbox
label={getMessageByLocale(
'component_projectCorrelationNetwork_title',
settings.locale
)}
defaultChecked={settings.projectNetwork}
onChange={async (e, checked) => {
settings.projectNetwork = checked;
await saveSettings(settings);
}}
/>
</Stack>
</Stack.Item>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_graphType_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale('options_graphType_title', settings.locale)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack style={{ margin: '10px 25px' }}>
<p>
{getMessageByLocale('options_graphType_toolTip', settings.locale)}{' '}
:
</p>
<ChoiceGroup
defaultSelectedKey={settings.graphType}
options={graphOptions}
onChange={async (e, option: any) => {
settings.graphType = option.key as GraphType;
await saveSettings(settings);
}}
/>
</Stack>
</Stack.Item>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_update_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale('options_update_title', settings.locale)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack
style={{ margin: '10px 25px' }}
tokens={{
childrenGap: 10,
}}
>
<p>
{getMessageByLocale('options_update_toolTip', settings.locale)}.
</p>
<Toggle
label={getMessageByLocale(
'options_update_toggle_autoCheck',
settings.locale
)}
defaultChecked={settings.checkForUpdates}
onText={getMessageByLocale(
'global_toggle_onText',
settings.locale
)}
offText={getMessageByLocale(
'global_toggle_offText',
settings.locale
)}
onChange={async (e, checked) => {
settings.checkForUpdates = checked;
await saveSettings(settings);
}}
/>
{checkingUpdate && (
<Stack horizontalAlign="start">
<Spinner
label={getMessageByLocale(
'options_update_checking',
settings.locale
)}
/>
</Stack>
)}
{updateStatus === UpdateStatus.yes && (
<MessageBar
messageBarType={MessageBarType.success}
isMultiline={false}
>
{getMessageByLocale(
'options_update_btn_updateStatusYes',
settings.locale
)}
<Link href={updateUrl} target="_blank" underline>
{getMessageByLocale(
'options_update_btn_getUpdate',
settings.locale
)}
</Link>
</MessageBar>
)}
{updateStatus === UpdateStatus.no && (
<MessageBar
messageBarType={MessageBarType.info}
isMultiline={false}
>
{getMessageByLocale(
'options_update_btn_updateStatusNo',
settings.locale
)}
</MessageBar>
)}
<DefaultButton
style={{
width: 120,
}}
disabled={checkingUpdate}
onClick={async () => {
await checkUpdateManually();
}}
>
{getMessageByLocale(
'options_update_btn_checkUpdate',
settings.locale
)}
</DefaultButton>
</Stack>
</Stack.Item>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_token_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale('options_token_title', settings.locale)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack
style={{ margin: '10px 25px' }}
tokens={{
childrenGap: 10,
}}
>
<p>
{getMessageByLocale('options_token_toolTip', settings.locale)} :
</p>
{tokenCurrent !== '' && (
<Stack
horizontal
verticalAlign="center"
style={{
margin: '5px',
padding: '3px',
width: '300px',
boxShadow: '4px 4px 10px rgba(0, 0, 0, 0.2)',
}}
tokens={{
childrenGap: 5,
}}
>
<Image
width={75}
height={75}
src={metaData.avatar}
imageFit={ImageFit.centerCover}
/>
<Text
variant="large"
style={{
marginLeft: 25,
maxWidth: 200,
wordWrap: 'break-word',
}}
>
{metaData.name}
</Text>
</Stack>
)}
<DefaultButton
onClick={() => {
setShowDialogToken(true);
}}
style={{
width: 120,
}}
>
{getMessageByLocale(
'options_token_btn_setToken',
settings.locale
)}
</DefaultButton>
</Stack>
</Stack.Item>
<Stack.Item className="Box">
<TooltipHost
content={getMessageByLocale(
'options_about_toolTip',
settings.locale
)}
>
<Stack.Item className="Box-header">
<h2 className="Box-title">
{getMessageByLocale('options_about_title', settings.locale)}
</h2>
</Stack.Item>
</TooltipHost>
<Stack style={{ margin: '10px 25px' }}>
<p>
{getMessageByLocale('options_about_description', settings.locale)}
</p>
<p>
{getMessageByLocale(
'options_about_description_website',
settings.locale
)}
</p>
<Link href={HYPERTRONS_CRX_WEBSITE} target="_blank" underline>
{HYPERTRONS_CRX_WEBSITE}
</Link>
</Stack>
</Stack.Item>
</Stack>
</Stack>
);
}
Example #11
Source File: Popup.tsx From hypertrons-crx with Apache License 2.0 | 4 votes |
Popup: React.FC = () => {
const [settings, setSettings] = useState(new Settings());
const [metaData, setMetaData] = useState(new MetaData());
const [inited, setInited] = useState(false);
useEffect(() => {
const initSettings = async () => {
const temp = await loadSettings();
setSettings(temp);
setInited(true);
};
if (!inited) {
initSettings();
}
}, [inited, settings]);
useEffect(() => {
const initMetaData = async () => {
const temp = await loadMetaData();
setMetaData(temp);
};
initMetaData();
}, []);
const saveSettings = async (settings: Settings) => {
setSettings(settings);
await chromeSet('settings', settings.toJson());
};
if (!inited) {
return <div />;
}
return (
<Stack horizontalAlign="center">
<Stack
horizontalAlign="space-around"
verticalAlign="center"
style={{ margin: '5px', padding: '3px' }}
tokens={{
childrenGap: 10,
}}
>
<Stack horizontalAlign="center">
<Toggle
label={getMessageByLocale(
'options_enable_toggle_autoCheck',
settings.locale
)}
defaultChecked={settings.isEnabled}
onText={getMessageByLocale('global_toggle_onText', settings.locale)}
offText={getMessageByLocale(
'global_toggle_offText',
settings.locale
)}
onChange={async (e, checked) => {
settings.isEnabled = checked;
await saveSettings(settings);
}}
/>
</Stack>
{metaData.token !== '' && (
<Stack
horizontal
verticalAlign="center"
style={{
margin: '5px',
padding: '3px',
width: '200px',
}}
tokens={{
childrenGap: 5,
}}
>
<Image
width={75}
height={75}
src={metaData.avatar}
imageFit={ImageFit.centerCover}
/>
<Text
variant="large"
style={{ marginLeft: 25, width: 100, wordWrap: 'break-word' }}
>
{metaData.name}
</Text>
</Stack>
)}
{metaData.token === '' && (
<DefaultButton
onClick={() => {
chrome.runtime.openOptionsPage();
}}
style={{
width: 120,
}}
>
{getMessageByLocale('options_token_title', settings.locale)}
</DefaultButton>
)}
</Stack>
</Stack>
);
}
Example #12
Source File: TrialsDetail.tsx From AIPerf with MIT License | 4 votes |
render(): React.ReactNode {
const { tablePageSize, whichGraph, searchType } = this.state;
const { columnList, changeColumn } = this.props;
const source = TRIALS.filter(this.state.searchFilter);
const trialIds = TRIALS.filter(this.state.searchFilter).map(trial => trial.id);
const searchOptions = [
{ key: 'Id', text: 'Id' },
{ key: 'Trial No.', text: 'Trial No.' },
{ key: 'Status', text: 'Status' },
{ key: 'Parameters', text: 'Parameters' },
];
return (
<div>
<div className="trial" id="tabsty">
<Pivot defaultSelectedKey={"0"} className="detial-title">
{/* <PivotItem tab={this.titleOfacc} key="1"> doesn't work*/}
<PivotItem headerText="Default metric" itemIcon="HomeGroup" key="1">
<Stack className="graph">
<DefaultPoint
trialIds={trialIds}
visible={whichGraph === '1'}
trialsUpdateBroadcast={this.props.trialsUpdateBroadcast}
/>
</Stack>
</PivotItem>
{/* <PivotItem tab={this.titleOfhyper} key="2"> */}
<PivotItem headerText="Hyper-parameter" itemIcon="Equalizer" key="2">
<Stack className="graph">
<Para
dataSource={source}
expSearchSpace={JSON.stringify(EXPERIMENT.searchSpace)}
whichGraph={whichGraph}
/>
</Stack>
</PivotItem>
{/* <PivotItem tab={this.titleOfDuration} key="3"> */}
<PivotItem headerText="Duration" itemIcon="BarChartHorizontal" key="3">
<Duration source={source} whichGraph={whichGraph} />
</PivotItem>
{/* <PivotItem tab={this.titleOfIntermediate} key="4"> */}
<PivotItem headerText="Intermediate result" itemIcon="StackedLineChart" key="4">
{/* *why this graph has small footprint? */}
<Intermediate source={source} whichGraph={whichGraph} />
</PivotItem>
</Pivot>
</div>
{/* trial table list */}
<Stack horizontal className="panelTitle">
<span style={{ marginRight: 12 }}>{tableListIcon}</span>
<span>Trial jobs</span>
</Stack>
<Stack horizontal className="allList">
<StackItem grow={50}>
<DefaultButton
text="Compare"
className="allList-compare"
// use child-component tableList's function, the function is in child-component.
onClick={(): void => { if (this.tableList) { this.tableList.compareBtn(); } }}
/>
</StackItem>
<StackItem grow={50}>
<Stack horizontal horizontalAlign="end" className="allList">
<DefaultButton
className="allList-button-gap"
text="Add column"
onClick={(): void => { if (this.tableList) { this.tableList.addColumn(); } }}
/>
<Dropdown
selectedKey={searchType}
options={searchOptions}
onChange={this.updateSearchFilterType}
styles={{ root: { width: 150 } }}
/>
<input
type="text"
className="allList-search-input"
placeholder={`Search by ${this.state.searchType}`}
onChange={this.searchTrial}
style={{ width: 230 }}
ref={(text): any => (this.searchInput) = text}
/>
</Stack>
</StackItem>
</Stack>
<TableList
pageSize={tablePageSize}
tableSource={source.map(trial => trial.tableRecord)}
columnList={columnList}
changeColumn={changeColumn}
trialsUpdateBroadcast={this.props.trialsUpdateBroadcast}
// TODO: change any to specific type
ref={(tabList): any => this.tableList = tabList}
/>
</div>
);
}
Example #13
Source File: LogDrawer.tsx From AIPerf with MIT License | 4 votes |
render(): React.ReactNode {
const { closeDrawer, activeTab } = this.props;
const { nniManagerLogStr, dispatcherLogStr, isLoading, logDrawerHeight } = this.state;
return (
<Stack>
<Panel
isOpen={true}
hasCloseButton={false}
isFooterAtBottom={true}
>
<div className="log-tab-body">
<Pivot
selectedKey={activeTab}
style={{ minHeight: 190, paddingTop: '16px' }}
>
{/* <PivotItem headerText={this.dispatcherHTML()} key="dispatcher" onLinkClick> */}
<PivotItem headerText="Dispatcher Log" key="dispatcher">
<MonacoHTML
content={dispatcherLogStr || 'Loading...'}
loading={isLoading}
// paddingTop[16] + tab[44] + button[32]
height={logDrawerHeight - 92}
/>
<Stack horizontal className="buttons">
<StackItem grow={12} className="download">
<PrimaryButton text="Download" onClick={this.downloadDispatcher} />
</StackItem>
<StackItem grow={12} className="close">
<DefaultButton text="Close" onClick={closeDrawer} />
</StackItem>
</Stack>
</PivotItem>
<PivotItem headerText="NNIManager Log" key="nnimanager">
{/* <TabPane tab="NNImanager Log" key="nnimanager"> */}
<MonacoHTML
content={nniManagerLogStr || 'Loading...'}
loading={isLoading}
height={logDrawerHeight - 92}
/>
<Stack horizontal className="buttons">
<StackItem grow={12} className="download">
<PrimaryButton text="Download" onClick={this.downloadNNImanager} />
</StackItem>
<StackItem grow={12} className="close">
<DefaultButton text="Close" onClick={closeDrawer} />
</StackItem>
</Stack>
</PivotItem>
</Pivot>
</div>
</Panel>
</Stack>
);
}
Example #14
Source File: NewSiteScriptPanel.tsx From sp-site-designs-studio with MIT License | 4 votes |
NewSiteScriptPanel = (props: INewSiteScriptPanelProps) => {
const [appContext, action] = useAppContext<IApplicationState, ActionType>();
// Get services instances
const siteScriptSchemaService = appContext.serviceScope.consume(SiteScriptSchemaServiceKey);
const siteDesignsService = appContext.serviceScope.consume(SiteDesignsServiceKey);
const [needsArguments, setNeedsArguments] = useState<boolean>(false);
const [creationArgs, setCreationArgs] = useState<ICreateArgs>({ from: "BLANK" });
const [fromWebArgs, setFromWebArgs] = useState<IGetSiteScriptFromWebOptions>(getDefaultFromWebArgs());
const [selectedSample, setSelectedSample] = useState<ISiteScriptSample>(null);
useEffect(() => {
setCreationArgs({ from: "BLANK" });
setNeedsArguments(false);
setFromWebArgs(getDefaultFromWebArgs());
}, [props.isOpen]);
const onCancel = () => {
if (props.onCancel) {
props.onCancel();
}
};
const onScriptAdded = async () => {
try {
let newSiteScriptContent: ISiteScriptContent = null;
let fromExistingResult: IGetSiteScriptFromExistingResourceResult = null;
switch (creationArgs.from) {
case "BLANK":
newSiteScriptContent = siteScriptSchemaService.getNewSiteScript();
break;
case "WEB":
fromExistingResult = await siteDesignsService.getSiteScriptFromWeb(creationArgs.webUrl, fromWebArgs);
newSiteScriptContent = fromExistingResult.JSON;
break;
case "LIST":
fromExistingResult = await siteDesignsService.getSiteScriptFromList(creationArgs.listUrl);
newSiteScriptContent = fromExistingResult.JSON;
break;
case "SAMPLE":
if (selectedSample) {
try {
const jsonWithIgnoredComments = selectedSample.jsonContent.replace(/\/\*(.*)\*\//g,'');
newSiteScriptContent = JSON.parse(jsonWithIgnoredComments);
} catch (error) {
action("SET_USER_MESSAGE", {
userMessage: {
message: "The JSON of this site script sample is unfortunately invalid... Please reach out to the maintainer to report this issue",
messageType: MessageBarType.error
}
});
}
} else {
console.error("The sample JSON is not defined.");
}
break;
}
const siteScript: ISiteScript = {
Id: null,
Title: null,
Description: null,
Version: 1,
Content: newSiteScriptContent
};
action("EDIT_SITE_SCRIPT", { siteScript } as IEditSiteScriptActionArgs);
} catch (error) {
console.error(error);
}
};
const onChoiceClick = (createArgs: ICreateArgs) => {
setCreationArgs(createArgs);
switch (createArgs.from) {
case "BLANK":
onScriptAdded();
break;
case "LIST":
setNeedsArguments(true);
break;
case "WEB":
setNeedsArguments(true);
break;
case "SAMPLE":
setNeedsArguments(true);
break;
}
};
const renderFromWebArgumentsForm = () => {
return <Stack tokens={{ childrenGap: 8 }}>
<SitePicker label="Site" onSiteSelected={webUrl => {
setCreationArgs({ ...creationArgs, webUrl });
}} serviceScope={appContext.serviceScope} />
<ListPicker serviceScope={appContext.serviceScope}
webUrl={creationArgs.webUrl}
label="Include lists"
multiselect
onListsSelected={(includeLists) => setFromWebArgs({ ...fromWebArgs, includeLists: !includeLists ? [] : includeLists.map(l => l.webRelativeUrl) })}
/>
<div className={styles.toggleRow}>
<div className={styles.column8}>Include Branding</div>
<div className={styles.column4}>
<Toggle checked={fromWebArgs && fromWebArgs.includeBranding} onChange={(_, includeBranding) => setFromWebArgs({ ...fromWebArgs, includeBranding })} />
</div>
</div>
<div className={styles.toggleRow}>
<div className={styles.column8}>Include Regional settings</div>
<div className={styles.column4}>
<Toggle checked={fromWebArgs && fromWebArgs.includeRegionalSettings} onChange={(_, includeRegionalSettings) => setFromWebArgs({ ...fromWebArgs, includeRegionalSettings })} />
</div>
</div>
<div className={styles.toggleRow}>
<div className={styles.column8}>Include Site external sharing capability</div>
<div className={styles.column4}>
<Toggle checked={fromWebArgs && fromWebArgs.includeSiteExternalSharingCapability} onChange={(_, includeSiteExternalSharingCapability) => setFromWebArgs({ ...fromWebArgs, includeSiteExternalSharingCapability })} />
</div>
</div>
<div className={styles.toggleRow}>
<div className={styles.column8}>Include theme</div>
<div className={styles.column4}>
<Toggle checked={fromWebArgs && fromWebArgs.includeTheme} onChange={(_, includeTheme) => setFromWebArgs({ ...fromWebArgs, includeTheme })} />
</div>
</div>
<div className={styles.toggleRow}>
<div className={styles.column8}>Include links to exported items</div>
<div className={styles.column4}>
<Toggle checked={fromWebArgs && fromWebArgs.includeLinksToExportedItems} onChange={(_, includeLinksToExportedItems) => setFromWebArgs({ ...fromWebArgs, includeLinksToExportedItems })} />
</div>
</div>
</Stack>;
};
const renderFromListArgumentsForm = () => {
return <Stack tokens={{ childrenGap: 8 }}>
<SitePicker label="Site" onSiteSelected={webUrl => {
setCreationArgs({ ...creationArgs, webUrl });
}} serviceScope={appContext.serviceScope} />
<ListPicker serviceScope={appContext.serviceScope}
webUrl={creationArgs.webUrl}
label="List"
onListSelected={(list) => setCreationArgs({ ...creationArgs, listUrl: list && list.url })}
/>
</Stack>;
};
const renderSamplePicker = () => {
return <SiteScriptSamplePicker
selectedSample={selectedSample}
onSelectedSample={setSelectedSample} />;
};
const renderArgumentsForm = () => {
if (!needsArguments) {
return null;
}
switch (creationArgs.from) {
case "LIST":
return renderFromListArgumentsForm();
case "WEB":
return renderFromWebArgumentsForm();
case "SAMPLE":
return renderSamplePicker();
default:
return null;
}
};
const validateArguments = () => {
if (!creationArgs) {
return false;
}
switch (creationArgs.from) {
case "SAMPLE":
return !!(selectedSample && selectedSample.jsonContent);
default:
return true;
}
};
const getPanelHeaderText = () => {
if (!needsArguments) {
return "Add a new Site Script";
}
switch (creationArgs.from) {
case "LIST":
return "Add a new Site Script from existing list";
case "WEB":
return "Add a new Site Script from existing site";
case "SAMPLE":
return "Add a new Site Script from samples";
default:
return "";
}
};
const panelType = creationArgs.from == "SAMPLE" ? PanelType.extraLarge : PanelType.smallFixedFar;
return <Panel type={panelType}
headerText={getPanelHeaderText()}
isOpen={props.isOpen}
onDismiss={onCancel}
onRenderFooterContent={() => needsArguments && <div className={styles.panelFooter}>
<Stack horizontalAlign="end" horizontal tokens={{ childrenGap: 25 }}>
<PrimaryButton text="Add Site Script" onClick={onScriptAdded} disabled={!validateArguments()} />
<DefaultButton text="Cancel" onClick={onCancel} />
</Stack>
</div>}>
<div className={styles.NewSiteScriptPanel}>
{!needsArguments && <Stack tokens={{ childrenGap: 20 }}>
<CompoundButton
iconProps={{ iconName: "PageAdd" }}
text="Blank"
secondaryText="Create a new blank Site Script"
onClick={() => onChoiceClick({ from: "BLANK" })}
/>
<CompoundButton
iconProps={{ iconName: "SharepointLogoInverse" }}
text="From Site"
secondaryText="Create a new Site Script from an existing site"
onClick={() => onChoiceClick({ from: "WEB" })}
/>
<CompoundButton
iconProps={{ iconName: "PageList" }}
text="From List"
secondaryText="Create a new Site Script from an existing list"
onClick={() => onChoiceClick({ from: "LIST" })}
/>
<CompoundButton
iconProps={{ iconName: "ProductCatalog" }}
text="From Sample"
secondaryText="Create a new Site Script from a sample"
onClick={() => onChoiceClick({ from: "SAMPLE" })}
/>
</Stack>}
{renderArgumentsForm()}
</div>
</Panel>;
}
Example #15
Source File: ExperimentDrawer.tsx From AIPerf with MIT License | 4 votes |
render(): React.ReactNode {
const { isVisble, closeExpDrawer } = this.props;
const { experiment, expDrawerHeight } = this.state;
return (
<Stack className="logDrawer">
<Panel
isOpen={isVisble}
hasCloseButton={false}
styles={{ root: { height: expDrawerHeight, paddingTop: 15 } }}
>
<Pivot style={{ minHeight: 190 }} className="log-tab-body">
<PivotItem headerText="Experiment Parameters">
<div className="just-for-log">
<MonacoEditor
width="100%"
// 92 + marginTop[16]
height={expDrawerHeight - 108}
language="json"
value={experiment}
options={DRAWEROPTION}
/>
</div>
<Stack horizontal className="buttons">
<StackItem grow={50} className="download">
<PrimaryButton
text="Download"
onClick={this.downExperimentParameters}
/>
</StackItem>
<StackItem grow={50} className="close">
<DefaultButton
text="Close"
onClick={closeExpDrawer}
/>
</StackItem>
</Stack>
</PivotItem>
</Pivot>
</Panel>
</Stack>
);
}
Example #16
Source File: CustomizedTrial.tsx From AIPerf with MIT License | 4 votes |
render(): React.ReactNode {
const { closeCustomizeModal, visible } = this.props;
const { isShowSubmitSucceed, isShowSubmitFailed, isShowWarning, customID, copyTrialParameter } = this.state;
const warning = 'The parameters you set are not in our search space, this may cause the tuner to crash, Are'
+ ' you sure you want to continue submitting?';
return (
<Stack>
<Dialog
hidden={!visible} // required field!
dialogContentProps={{
type: DialogType.largeHeader,
title: 'Customized trial setting',
subText: 'You can submit a customized trial.'
}}
modalProps={{
isBlocking: false,
styles: { main: { maxWidth: 450 } }
}}
>
<form className="hyper-box">
{
Object.keys(copyTrialParameter).map(item => (
<Stack horizontal key={item} className="hyper-form">
<StackItem styles={{ root: { minWidth: 100 } }} className="title">{item}</StackItem>
<StackItem className="inputs">
<input
type="text"
name={item}
defaultValue={copyTrialParameter[item]}
onChange={this.getFinalVal}
/>
</StackItem>
</Stack>
)
)
}
{/* disable [tag] because we havn't support */}
{/* <Stack key="tag" horizontal className="hyper-form tag-input">
<StackItem grow={9} className="title">Tag</StackItem>
<StackItem grow={15} className="inputs">
<input type="text" value='Customized' />
</StackItem>
</Stack> */}
</form>
<DialogFooter>
<PrimaryButton text="Submit" onClick={this.addNewTrial} />
<DefaultButton text="Cancel" onClick={closeCustomizeModal} />
</DialogFooter>
</Dialog>
{/* clone: prompt succeed or failed */}
<Dialog
hidden={!isShowSubmitSucceed}
onDismiss={this.closeSucceedHint}
dialogContentProps={{
type: DialogType.normal,
title: <div className="icon-color">{completed}<b>Submit successfully</b></div>,
closeButtonAriaLabel: 'Close',
subText: `You can find your customized trial by Trial No.${customID}`
}}
modalProps={{
isBlocking: false,
styles: { main: { minWidth: 500 } },
}}
>
<DialogFooter>
<PrimaryButton onClick={this.closeSucceedHint} text="OK" />
</DialogFooter>
</Dialog>
<Dialog
hidden={!isShowSubmitFailed}
onDismiss={this.closeSucceedHint}
dialogContentProps={{
type: DialogType.normal,
title: <div className="icon-error">{errorBadge}Submit Failed</div>,
closeButtonAriaLabel: 'Close',
subText: 'Unknown error.'
}}
modalProps={{
isBlocking: false,
styles: { main: { minWidth: 500 } },
}}
>
<DialogFooter>
<PrimaryButton onClick={this.closeFailedHint} text="OK" />
</DialogFooter>
</Dialog>
{/* hyperParameter not match search space, warning modal */}
<Dialog
hidden={!isShowWarning}
onDismiss={this.closeSucceedHint}
dialogContentProps={{
type: DialogType.normal,
title: <div className="icon-error">{warining}Warning</div>,
closeButtonAriaLabel: 'Close',
subText: `${warning}`
}}
modalProps={{
isBlocking: false,
styles: { main: { minWidth: 500 } },
}}
>
<DialogFooter>
<PrimaryButton onClick={this.warningConfirm} text="Confirm" />
<DefaultButton onClick={this.warningCancel} text="Cancel" />
</DialogFooter>
</Dialog>
</Stack>
);
}
Example #17
Source File: SiteScriptEditor.tsx From sp-site-designs-studio with MIT License | 3 votes |
SiteScriptEditor = (props: ISiteScriptEditorProps) => {
useTraceUpdate('SiteScriptEditor', props);
const [appContext, execute] = useAppContext<IApplicationState, ActionType>();
// Get service references
const siteDesignsService = appContext.serviceScope.consume(SiteDesignsServiceKey);
const siteScriptSchemaService = appContext.serviceScope.consume(SiteScriptSchemaServiceKey);
const exportService = appContext.serviceScope.consume(ExportServiceKey);
const [state, dispatchState] = useReducer(SiteScriptEditorReducer, {
siteScriptMetadata: null,
siteScriptContent: null,
currentExportPackage: null,
currentExportType: "json",
isExportUIVisible: false,
isSaving: false,
isAssociatingToSiteDesign: false,
isValidCode: true,
updatedContentFrom: null
});
const { siteScriptMetadata,
siteScriptContent,
isValidCode,
isExportUIVisible,
currentExportType,
currentExportPackage,
isAssociatingToSiteDesign,
isSaving } = state;
// Use refs
const codeEditorRef = useRef<any>();
const titleFieldRef = useRef<any>();
const selectedSiteDesignRef = useRef<string>();
const setLoading = (loading: boolean) => {
execute("SET_LOADING", { loading });
};
// Use Effects
useEffect(() => {
if (!props.siteScript.Id) {
dispatchState({ type: "SET_SITE_SCRIPT", siteScript: props.siteScript });
if (titleFieldRef.current) {
titleFieldRef.current.focus();
}
return;
}
setLoading(true);
console.debug("Loading site script...", props.siteScript.Id);
siteDesignsService.getSiteScript(props.siteScript.Id).then(loadedSiteScript => {
dispatchState({ type: "SET_SITE_SCRIPT", siteScript: loadedSiteScript });
console.debug("Loaded: ", loadedSiteScript);
}).catch(error => {
console.error(`The Site Script ${props.siteScript.Id} could not be loaded`, error);
}).then(() => {
setLoading(false);
});
}, [props.siteScript]);
const onTitleChanged = (ev: any, title: string) => {
const siteScript = { ...siteScriptMetadata, Title: title };
dispatchState({ type: "UPDATE_SITE_SCRIPT_METADATA", siteScript });
};
let currentDescription = useRef<string>(siteScriptMetadata && siteScriptMetadata.Description);
const onDescriptionChanging = (ev: any, description: string) => {
currentDescription.current = description;
};
const onDescriptionInputBlur = (ev: any) => {
const siteScript = { ...siteScriptMetadata, Description: currentDescription.current };
dispatchState({ type: "UPDATE_SITE_SCRIPT_METADATA", siteScript });
};
const onVersionChanged = (ev: any, version: string) => {
const versionInt = parseInt(version);
if (!isNaN(versionInt)) {
const siteScript = { ...siteScriptMetadata, Version: versionInt };
dispatchState({ type: "UPDATE_SITE_SCRIPT_METADATA", siteScript });
}
};
const onSiteScriptContentUpdatedFromUI = (content: ISiteScriptContent) => {
dispatchState({ type: "UPDATE_SITE_SCRIPT_CONTENT", content, from: "UI" });
};
const onSave = async () => {
dispatchState({ type: "SET_ISSAVING", isSaving: true });
try {
const isNewSiteScript = !siteScriptMetadata.Id;
const toSave: ISiteScript = { ...siteScriptMetadata, Content: state.siteScriptContent };
const updated = await siteDesignsService.saveSiteScript(toSave);
const refreshedSiteScripts = await siteDesignsService.getSiteScripts();
execute("SET_USER_MESSAGE", {
userMessage: {
message: `${siteScriptMetadata.Title} has been successfully saved.`,
messageType: MessageBarType.success
}
} as ISetUserMessageArgs);
execute("SET_ALL_AVAILABLE_SITE_SCRIPTS", { siteScripts: refreshedSiteScripts } as ISetAllAvailableSiteScripts);
dispatchState({ type: "SET_SITE_SCRIPT", siteScript: updated });
if (isNewSiteScript) {
// Ask if the new Site Script should be associated to a Site Design
if (await Confirm.show({
title: `Associate to Site Design`,
message: `Do you want to associate the new ${(siteScriptMetadata && siteScriptMetadata.Title)} to a Site Design ?`,
cancelLabel: 'No',
okLabel: 'Yes'
})) {
dispatchState({ type: "SET_ISASSOCIATINGTOSITEDESIGN", isAssociatingToSiteDesign: true });
}
}
} catch (error) {
execute("SET_USER_MESSAGE", {
userMessage: {
message: `${siteScriptMetadata.Title} could not be saved. Please make sure you have SharePoint administrator privileges...`,
messageType: MessageBarType.error
}
} as ISetUserMessageArgs);
console.error(error);
}
dispatchState({ type: "SET_ISSAVING", isSaving: false });
};
const onDelete = async () => {
if (!await Confirm.show({
title: `Delete Site Script`,
message: `Are you sure you want to delete ${(siteScriptMetadata && siteScriptMetadata.Title) || "this Site Script"} ?`
})) {
return;
}
dispatchState({ type: "SET_ISSAVING", isSaving: true });
try {
await siteDesignsService.deleteSiteScript(siteScriptMetadata);
const refreshedSiteScripts = await siteDesignsService.getSiteScripts();
execute("SET_USER_MESSAGE", {
userMessage: {
message: `${siteScriptMetadata.Title} has been successfully deleted.`,
messageType: MessageBarType.success
}
} as ISetUserMessageArgs);
execute("SET_ALL_AVAILABLE_SITE_SCRIPTS", { siteScripts: refreshedSiteScripts } as ISetAllAvailableSiteScripts);
execute("GO_TO", { page: "SiteScriptsList" } as IGoToActionArgs);
} catch (error) {
execute("SET_USER_MESSAGE", {
userMessage: {
message: `${siteScriptMetadata.Title} could not be deleted. Please make sure you have SharePoint administrator privileges...`,
messageType: MessageBarType.error
}
} as ISetUserMessageArgs);
console.error(error);
}
dispatchState({ type: "SET_ISSAVING", isSaving: false });
};
const onAssociateSiteScript = () => {
if (selectedSiteDesignRef.current != NEW_SITE_DESIGN_KEY) {
execute("EDIT_SITE_DESIGN", { siteDesign: { Id: selectedSiteDesignRef.current }, additionalSiteScriptIds: [siteScriptMetadata.Id] });
} else if (selectedSiteDesignRef.current) {
execute("EDIT_SITE_DESIGN", { siteDesign: createNewSiteDesign(), additionalSiteScriptIds: [siteScriptMetadata.Id] });
}
};
const onExportRequested = (exportType?: ExportType) => {
const toExport: ISiteScript = { ...siteScriptMetadata, Content: siteScriptContent };
let exportPromise: Promise<ExportPackage> = null;
switch (exportType) {
case "PnPPowershell":
exportPromise = exportService.generateSiteScriptPnPPowershellExportPackage(toExport);
break;
case "PnPTemplate":
break; // Not yet supported
case "o365_PS":
exportPromise = exportService.generateSiteScriptO365CLIExportPackage(toExport, "Powershell");
break;
case "o365_Bash":
exportPromise = exportService.generateSiteScriptO365CLIExportPackage(toExport, "Bash");
break;
case "json":
default:
exportPromise = exportService.generateSiteScriptJSONExportPackage(toExport);
break;
}
if (exportPromise) {
exportPromise.then(exportPackage => {
dispatchState({ type: "SET_EXPORTPACKAGE", exportPackage, exportType });
});
}
};
let codeUpdateTimeoutHandle: any = null;
const onCodeChanged = (updatedCode: string) => {
if (!updatedCode) {
return;
}
if (codeUpdateTimeoutHandle) {
clearTimeout(codeUpdateTimeoutHandle);
}
// if (updatedContentFrom == "UI") {
// // Not trigger the change of state if the script content was updated from UI
// console.debug("The code has been modified after a change in designer. The event will not be propagated");
// dispatchState({ type: "UPDATE_SITE_SCRIPT", siteScript: null, from: "CODE" });
// return;
// }
codeUpdateTimeoutHandle = setTimeout(() => {
try {
const jsonWithIgnoredComments = updatedCode.replace(/\/\*(.*)\*\//g,'');
if (siteScriptSchemaService.validateSiteScriptJson(jsonWithIgnoredComments)) {
const content = JSON.parse(jsonWithIgnoredComments) as ISiteScriptContent;
dispatchState({ type: "UPDATE_SITE_SCRIPT_CONTENT", content, isValidCode: true, from: "CODE" });
} else {
dispatchState({ type: "UPDATE_SITE_SCRIPT_CONTENT", content: null, isValidCode: false, from: "CODE" });
}
} catch (error) {
console.warn("Code is not valid site script JSON");
}
}, 500);
};
const editorDidMount = (_, editor) => {
const schema = siteScriptSchemaService.getSiteScriptSchema();
codeEditorRef.current = editor;
monaco.init().then(monacoApi => {
monacoApi.languages.json.jsonDefaults.setDiagnosticsOptions({
schemas: [{
uri: 'schema.json',
schema
}],
validate: true,
allowComments: false
});
}).catch(error => {
console.error("An error occured while trying to configure code editor");
});
const editorModel = editor.getModel();
console.log("Editor model: ", editorModel);
editor.onDidChangeModelContent(ev => {
if (codeEditorRef && codeEditorRef.current) {
onCodeChanged(codeEditorRef.current.getValue());
}
});
};
const checkIsValidForSave: () => [boolean, string?] = () => {
if (!siteScriptMetadata) {
return [false, "Current Site Script not defined"];
}
if (!siteScriptMetadata.Title) {
return [false, "Please set the title of the Site Script..."];
}
if (!isValidCode) {
return [false, "Please check the validity of the code..."];
}
return [true];
};
const isLoading = appContext.isLoading;
const [isValidForSave, validationMessage] = checkIsValidForSave();
if (!siteScriptMetadata || !siteScriptContent) {
return null;
}
return <div className={styles.SiteScriptEditor}>
<div className={styles.row}>
<div className={styles.columnLayout}>
<div className={styles.row}>
<div className={styles.column11}>
<TextField
styles={{
field: {
fontSize: "32px",
lineHeight: "45px",
height: "45px"
},
root: {
height: "60px",
marginTop: "5px",
marginBottom: "5px"
}
}}
placeholder="Enter the name of the Site Script..."
borderless
componentRef={titleFieldRef}
value={siteScriptMetadata.Title}
onChange={onTitleChanged} />
{isLoading && <ProgressIndicator />}
</div>
{!isLoading && <div className={`${styles.column1} ${styles.righted}`}>
<Stack horizontal horizontalAlign="end" tokens={{ childrenGap: 15 }}>
<CommandButton disabled={isSaving} iconProps={{ iconName: "More" }} menuProps={{
items: [
(siteScriptMetadata.Id && {
key: 'deleteScript',
text: 'Delete',
iconProps: { iconName: 'Delete' },
onClick: onDelete
}),
{
key: 'export',
text: 'Export',
iconProps: { iconName: 'Download' },
onClick: () => onExportRequested(),
disabled: !isValidForSave
}
].filter(i => !!i),
} as IContextualMenuProps} />
<PrimaryButton disabled={isSaving || !isValidForSave} text="Save" iconProps={{ iconName: "Save" }} onClick={() => onSave()} />
</Stack>
</div>}
</div>
<div className={styles.row}>
{siteScriptMetadata.Id && <div className={styles.half}>
<div className={styles.row}>
<div className={styles.column8}>
<TextField
label="Id"
readOnly
value={siteScriptMetadata.Id} />
</div>
<div className={styles.column4}>
<TextField
label="Version"
value={siteScriptMetadata.Version.toString()}
onChange={onVersionChanged} />
</div>
</div>
</div>}
<div className={styles.half}>
<TextField
label="Description"
value={siteScriptMetadata.Description}
multiline={true}
rows={2}
borderless
placeholder="Enter a description for the Site Script..."
onChange={onDescriptionChanging}
onBlur={onDescriptionInputBlur}
/>
</div>
</div>
<div className={styles.row}>
<div className={styles.column}>
<Label>Actions</Label>
</div>
</div>
<div className={styles.row}>
<div className={styles.designerWorkspace}>
<SiteScriptDesigner
siteScriptContent={siteScriptContent}
onSiteScriptContentUpdated={onSiteScriptContentUpdatedFromUI} />
</div>
<div className={styles.codeEditorWorkspace}>
<CodeEditor
height="80vh"
language="json"
options={{
folding: true,
renderIndentGuides: true,
minimap: {
enabled: false
}
}}
value={toJSON(siteScriptContent)}
editorDidMount={editorDidMount}
/>
</div>
</div>
</div>
</div>
{/* Association to a Site Design */}
<Panel isOpen={isAssociatingToSiteDesign}
type={PanelType.smallFixedFar}
headerText="Associate to a Site Design"
onRenderFooterContent={(p) => <Stack horizontalAlign="end" horizontal tokens={{ childrenGap: 10 }}>
<PrimaryButton iconProps={{ iconName: "Check" }} text="Continue" onClick={() => onAssociateSiteScript()} />
<DefaultButton text="Cancel" onClick={() => dispatchState({ type: "SET_ISASSOCIATINGTOSITEDESIGN", isAssociatingToSiteDesign: false })} /></Stack>}
>
<SiteDesignPicker serviceScope={appContext.serviceScope}
label="Site Design"
onSiteDesignSelected={(siteDesignId) => {
console.log("Selected site design: ", siteDesignId);
selectedSiteDesignRef.current = siteDesignId;
}}
hasNewSiteDesignOption
displayPreview />
</Panel>
{/* Export options */}
<Panel isOpen={isExportUIVisible}
type={PanelType.large}
headerText="Export Site Script"
onRenderFooterContent={(p) => <Stack horizontalAlign="end" horizontal tokens={{ childrenGap: 10 }}>
<PrimaryButton iconProps={{ iconName: "Download" }} text="Download" onClick={() => currentExportPackage && currentExportPackage.download()} />
<DefaultButton text="Cancel" onClick={() => dispatchState({ type: "SET_EXPORTPACKAGE", exportPackage: null })} /></Stack>}>
<Pivot
selectedKey={currentExportType}
onLinkClick={(item) => onExportRequested(item.props.itemKey as ExportType)}
headersOnly={true}
>
<PivotItem headerText="JSON" itemKey="json" />
<PivotItem headerText="PnP Powershell" itemKey="PnPPowershell" />
{/* <PivotItem headerText="PnP Template" itemKey="PnPTemplate" /> */}
<PivotItem headerText="O365 CLI (Powershell)" itemKey="o365_PS" />
<PivotItem headerText="O365 CLI (Bash)" itemKey="o365_Bash" />
</Pivot>
{currentExportPackage && <ExportPackageViewer exportPackage={currentExportPackage} />}
</Panel>
</div >;
}