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

Image editor webpart enhancements #5278

Merged
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
2 changes: 2 additions & 0 deletions samples/react-image-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ References to office-ui-fabric-react version 5.x because of SharePoint 2019 Supp
## Contributors

* [Peter Paul Kirschner](https://github.com/petkir)
* [Ishai Sagi] (http://github.com/ishaisagi-hns)

Thanks to [celum](https://www.celum.com/) and [cubido](https://www.cubido.at/) to allow to share this code.

## Version history

Version|Date|Comments
-------|----|--------
1.1.0.0|Sep 09, 2024|Added properties and accessibility
1.0.0.0|Mar 17, 2021|Initial release

## Minimal Path to Awesome
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ export interface IImageManipulationProps {
editMode?: (mode: boolean) => void;
configSettings: IImageManipulationConfig;
displayMode: DisplayMode;
altText: string;
}

export interface IImageManipulationState {
settingPanel: SettingPanelType;
redosettings: IImageManipulationSettings[];
lockAspectCrop: boolean;
lockAspectResize: boolean;
}

export class ImageManipulation extends React.Component<IImageManipulationProps, IImageManipulationState> {
Expand All @@ -81,7 +84,9 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,

this.state = {
settingPanel: SettingPanelType.Closed,
redosettings: []
redosettings: [],
lockAspectCrop: true,
lockAspectResize: true
};
this.openPanel = this.openPanel.bind(this);
this.setRotate = this.setRotate.bind(this);
Expand Down Expand Up @@ -109,6 +114,7 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
this.img = new Image();
this.img.src = url;
this.img.crossOrigin = 'Anonymous';
this.img.alt = this.props.altText ? this.props.altText : 'Untitled image';
this.img.onload = () => {

this.applySettings();
Expand Down Expand Up @@ -305,7 +311,7 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
<canvas className={this.getMaxWidth()}
style={{ display: 'none' }}
ref={this.setManipulateRef}></canvas>
<canvas className={this.getMaxWidth()} ref={this.setCanvasRef} ></canvas>
<canvas className={this.getMaxWidth()} ref={this.setCanvasRef} aria-label={this.props.altText} role='img' >Your browser does not support displaying canvas elements.</canvas>
{this.state.settingPanel === SettingPanelType.Crop && (this.getCropGrid())}
{this.state.settingPanel === SettingPanelType.Resize && (this.getResizeGrid())}

Expand Down Expand Up @@ -600,17 +606,20 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
return (<div>
<Checkbox
label={strings.LockAspect}
checked={!isNaN(crop.aspect)}
onChange={() => {
if (isNaN(crop.aspect)) {
this.setCrop(undefined, undefined, undefined, undefined, this.getAspect());
} else {
this.setCrop(undefined, undefined, undefined, undefined, undefined);
}

checked={this.state.lockAspectCrop}
onChange={(e, checked) => {
// Toggle the lockAspect state when checkbox is checked/unchecked
this.setState({ lockAspectCrop: checked }, () => {
// Call the setCrop function with appropriate arguments based on the new state
if (this.state.lockAspectCrop) {
this.setCrop(undefined, undefined, undefined, undefined, this.getAspect());
} else {
this.setCrop(undefined, undefined, undefined, undefined, undefined);
}
});
}}

/>

<TextField
label={strings.SourceX}
value={'' + crop.sx}
Expand Down Expand Up @@ -640,13 +649,16 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,

<Checkbox
label={strings.LockAspect}
checked={!isNaN(resize.aspect)}
checked={this.state.lockAspectResize}
onChange={() => {
if (isNaN(resize.aspect)) {
this.setResize(undefined, undefined, this.getAspect());
} else {
this.setResize(undefined, undefined, undefined);
}
this.setState({ lockAspectResize: !this.state.lockAspectResize }, () => {
if (isNaN(resize.aspect)) {
this.setResize(undefined, undefined, this.getAspect());
} else {
this.setResize(undefined, undefined, undefined);
}
})


}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
"group": { "default": "Other" },
"title": { "default": "react-image-editor" },
"description": { "default": "react-image-editor description" },
"title": { "default": "Advanced Image Editor" },
"description": { "default": "Add an image to the page, resize and edit the image." },
"officeFabricIconFontName": "Page",
"properties": {
"title": "react-image-editor Sample",
"showTitle":true,
"title": "Advanced Image Editor",
"showTitle":false,
"showEditIcon":false,
"settings":[],
"url":""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneLabel,
PropertyPaneTextField,
PropertyPaneToggle
} from '@microsoft/sp-webpart-base';

Expand All @@ -28,6 +30,10 @@ export default class ReactImageEditorWebPart extends BaseClientSideWebPart<IReac
title: this.properties.title,
url: this.properties.url,
settings: this.properties.settings,
showEditIcon:this.properties.showEditIcon,
altText:this.properties.altText,



updateTitleProperty: (value: string) => { this.properties.title = value; },
updateUrlProperty: (value: string) => {
Expand Down Expand Up @@ -67,9 +73,16 @@ export default class ReactImageEditorWebPart extends BaseClientSideWebPart<IReac
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('altText',{label:strings.AltTextFieldLabel}),
PropertyPaneToggle('showTitle', {
label: strings.ShowTitleFieldLabel
})
,
PropertyPaneToggle('showEditIcon', {
label: strings.ShowEditIconFieldLabel
}),
PropertyPaneLabel('urlInfo',{text:`The selected image is at ${this.properties.url?this.properties.url:'Not yet selected'} `})

]
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { ImageManipulation, IImageManipulationSettings } from '../../../componen

export interface IReactImageEditorBaseProps {
showTitle: boolean;
showEditIcon: boolean;
title: string;
url?: string;
settings?: IImageManipulationSettings[];
altText?: string;

}

Expand All @@ -21,6 +23,7 @@ export interface IReactImageEditorProps extends IReactImageEditorBaseProps {
updateTitleProperty: (value: string) => void;
updateUrlProperty: (value: string) => void;
updateManipulationSettingsProperty: (value: IImageManipulationSettings[]) => void;

}

export interface IReactImageEditorState {
Expand All @@ -46,14 +49,16 @@ export default class ReactImageEditor extends React.Component<IReactImageEditorP
return (

<div className={styles.reactImageEditor}>
<WebPartTitle displayMode={this.props.displayMode}
title={this.props.title}
updateProperty={this.props.updateTitleProperty} />
{(isFilePickerOpen || isConfigured) && Environment.type !== EnvironmentType.Local &&
{this.props.showTitle &&
<WebPartTitle displayMode={this.props.displayMode}
title={this.props.title}
updateProperty={this.props.updateTitleProperty} />
}
{(isFilePickerOpen || (isConfigured && this.props.displayMode === DisplayMode.Edit)) && Environment.type !== EnvironmentType.Local &&
<FilePicker
isPanelOpen={isFilePickerOpen}
accepts={['.gif', '.jpg', '.jpeg', '.png']}
buttonIcon='FileImage'
buttonIcon={'FileImage'}
onSave={(filePickerResult: IFilePickerResult) => {
this.setState({ isFilePickerOpen: false }, () => this._onUrlChanged(filePickerResult.fileAbsoluteUrl));
}}
Expand All @@ -65,6 +70,7 @@ export default class ReactImageEditor extends React.Component<IReactImageEditorP

}}
context={this.props.context}

/>}

{!isConfigured ? (<Placeholder iconName='Edit'
Expand All @@ -73,16 +79,16 @@ export default class ReactImageEditor extends React.Component<IReactImageEditorP
buttonLabel='Configure'
onConfigure={this._onConfigure} />) :
(
<ImageManipulation
settings={this.props.settings}
configSettings={{
rotateButtons: [-90, -45, -30, 0, 30, 45, 90]
}
}
displayMode={this.props.displayMode}
settingsChanged={this._onSettingsChanged}
src={this.props.url}
/>
<ImageManipulation
settings={this.props.settings}
configSettings={{
rotateButtons: [-90, -45, -30, 0, 30, 45, 90]
}
}
displayMode={this.props.displayMode}
settingsChanged={this._onSettingsChanged}
src={this.props.url} altText={this.props.altText}
/>
)}

</div >
Expand All @@ -95,7 +101,7 @@ export default class ReactImageEditor extends React.Component<IReactImageEditorP
this._onUrlChanged(
'https://media.gettyimages.com/photos/'
+ 'whitewater-paddlers-descend-vertical-waterfall-in-kayak-picture-id1256321293?s=2048x2048'
);
);
});
} else {
this.setState({ isFilePickerOpen: true });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"ShowTitleFieldLabel": "Show webpart title"
"PropertyPaneDescription": "",
"BasicGroupName": "Web part configuration",
"ShowTitleFieldLabel": "Show webpart title",
"ShowEditIconFieldLabel": "Show edit icon",
"AltTextFieldLabel":"Alt Text"

}
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ declare interface IReactImageEditorWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
ShowTitleFieldLabel: string;
ShowEditIconFieldLabel: string;
AltTextFieldLabel: string;
}

declare module 'ReactImageEditorWebPartStrings' {
Expand Down
Loading