355 lines
10 KiB
Markdown
355 lines
10 KiB
Markdown
# Edison PowerPoint Add-in Developer Documentation
|
|
|
|
This document provides detailed technical information for developers working on the Edison PowerPoint Add-in.
|
|
|
|
## Architecture Overview
|
|
|
|
Edison is a PowerPoint add-in built with:
|
|
- **TypeScript** for type-safe code
|
|
- **React** for UI components
|
|
- **Office.js API** for PowerPoint integration
|
|
- **Fluent UI** for Microsoft-style interface components
|
|
|
|
The application follows a component-based architecture where each tool is encapsulated in its own React component.
|
|
|
|
## UML Diagrams
|
|
|
|
To better understand the architecture and structure of the Edison PowerPoint Add-in, refer to the following UML diagrams:
|
|
|
|
- [UML Diagrams Index](powerpoint-toolbox-uml-index.md) - Overview and index of all UML diagrams
|
|
- [Component Relationships](powerpoint-toolbox-uml.md) - Shows the relationships between React components
|
|
- [Project Structure](powerpoint-toolbox-structure-uml.md) - Illustrates the file and directory organization
|
|
- [Data Flow](powerpoint-toolbox-dataflow-uml.md) - Demonstrates the flow of data and interactions
|
|
|
|
These diagrams provide visual representations of the application's architecture, component relationships, and data flow patterns, which can help new developers understand the codebase more quickly.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
/
|
|
├── assets/ # Images and icons
|
|
├── dist/ # Build output (generated)
|
|
├── src/
|
|
│ ├── commands/ # Command handlers
|
|
│ │ ├── commands.html # HTML for command UI
|
|
│ │ └── commands.ts # Command implementations
|
|
│ └── taskpane/ # Main add-in UI
|
|
│ ├── components/ # React components
|
|
│ │ ├── ActionButton.tsx # Reusable button with error handling
|
|
│ │ ├── AlignmentButtons.tsx
|
|
│ │ ├── App.tsx # Main application component
|
|
│ │ ├── ConfidentialButtons.tsx
|
|
│ │ ├── DraftButtons.tsx
|
|
│ │ ├── GridGuidelineManager.tsx
|
|
│ │ ├── Header.tsx
|
|
│ │ ├── InsertTitles.tsx
|
|
│ │ ├── MatchProperties.tsx
|
|
│ │ ├── MatchSizes.tsx
|
|
│ │ ├── ProgressBarButtons.tsx
|
|
│ │ ├── RoundImage.tsx
|
|
│ │ ├── Section.tsx # Reusable section component
|
|
│ │ ├── SmartTextFormatter.tsx
|
|
│ │ ├── SwapPositions.tsx
|
|
│ │ └── commonStyles.tsx
|
|
│ ├── types/ # TypeScript type definitions
|
|
│ │ └── office-types.ts # Office API type utilities
|
|
│ ├── index.tsx # Entry point
|
|
│ └── taskpane.html # Main HTML container
|
|
├── babel.config.json # Babel configuration
|
|
├── manifest.xml # Add-in manifest
|
|
├── package.json # Dependencies and scripts
|
|
├── tsconfig.json # TypeScript configuration
|
|
└── webpack.config.js # Webpack configuration
|
|
```
|
|
|
|
## Development Environment Setup
|
|
|
|
### Prerequisites
|
|
|
|
- Node.js (LTS version recommended)
|
|
- npm
|
|
- Microsoft PowerPoint (desktop version)
|
|
|
|
### Setup Steps
|
|
|
|
1. Clone the repository:
|
|
```bash
|
|
git clone https://github.com/your-org/edison-powerpoint-addin.git
|
|
cd edison-powerpoint-addin
|
|
```
|
|
|
|
2. Install dependencies:
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. Build the project:
|
|
```bash
|
|
npm run build:dev
|
|
```
|
|
|
|
4. Start the development server:
|
|
```bash
|
|
npm run dev-server
|
|
```
|
|
|
|
5. Start the add-in in PowerPoint:
|
|
```bash
|
|
npm run start
|
|
```
|
|
|
|
### Local Development Certificates
|
|
|
|
Office Add-ins require HTTPS even for local development. The `office-addin-dev-certs` package is used to create and install self-signed certificates for development.
|
|
|
|
If you encounter certificate issues, run:
|
|
```bash
|
|
npx office-addin-dev-certs install
|
|
```
|
|
|
|
## Component Development Guidelines
|
|
|
|
### Reusable Components
|
|
|
|
#### ActionButton
|
|
A reusable button component that handles error states, loading states, and consistent styling:
|
|
|
|
```tsx
|
|
import ActionButton from "./ActionButton";
|
|
|
|
// In your component:
|
|
<ActionButton
|
|
title="Match Sizes"
|
|
icon={<ArrowFitInRegular />}
|
|
onClick={myAsyncFunction}
|
|
/>
|
|
```
|
|
|
|
#### Section
|
|
A consistent container for organizing the UI:
|
|
|
|
```tsx
|
|
import Section from "./Section";
|
|
|
|
// In your component:
|
|
<Section title="My Feature Group">
|
|
<MyFeatureComponent />
|
|
</Section>
|
|
```
|
|
|
|
### Creating a New Tool
|
|
|
|
1. Create a new component file in `src/taskpane/components/`
|
|
2. Import the necessary Office.js APIs and React hooks
|
|
3. Use the StatusContext for user feedback
|
|
4. Follow the pattern of existing components:
|
|
- Use the `PowerPoint.run()` method for PowerPoint operations
|
|
- Provide clear success/error messaging
|
|
- Handle selection states appropriately
|
|
|
|
Example component structure:
|
|
```tsx
|
|
import * as React from "react";
|
|
import { useState } from "react";
|
|
import { Button } from "@fluentui/react-components";
|
|
import { useStatusContext } from "./App";
|
|
|
|
const MyNewTool: React.FC = () => {
|
|
const { setStatusMessage, setStatusType, isProcessing, setIsProcessing } = useStatusContext();
|
|
|
|
const performAction = async () => {
|
|
setIsProcessing(true);
|
|
try {
|
|
await PowerPoint.run(async (context) => {
|
|
// Implement your PowerPoint operations here
|
|
await context.sync();
|
|
});
|
|
setStatusMessage("Operation completed successfully!");
|
|
setStatusType("success");
|
|
} catch (error) {
|
|
setStatusMessage(`Error: ${error.message}`);
|
|
setStatusType("error");
|
|
console.error("Operation error:", error);
|
|
} finally {
|
|
setIsProcessing(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Button onClick={performAction} disabled={isProcessing}>
|
|
My New Tool
|
|
</Button>
|
|
);
|
|
};
|
|
|
|
export default MyNewTool;
|
|
```
|
|
|
|
### Common PowerPoint.js Operations
|
|
|
|
#### Type-Safe Utilities
|
|
The application provides type-safe utility functions in `src/taskpane/types/office-types.ts`:
|
|
|
|
```typescript
|
|
// Get error message safely from any error type
|
|
const errorMsg = getErrorMessage(error);
|
|
|
|
// Check if a shape is an image
|
|
if (isPictureShape(shape)) {
|
|
// It's a picture shape
|
|
}
|
|
|
|
// Get the first selected slide
|
|
const slide = getFirstSelectedSlide(context);
|
|
|
|
// Select shapes by ID
|
|
selectShapesById(slide, [shape1.id, shape2.id]);
|
|
```
|
|
|
|
#### Selecting Shapes
|
|
```typescript
|
|
const shapes = context.presentation.getSelectedShapes();
|
|
shapes.load("items");
|
|
await context.sync();
|
|
```
|
|
|
|
#### Working with Slide Masters
|
|
```typescript
|
|
const slideMasters = context.presentation.slideMasters;
|
|
slideMasters.load("items");
|
|
await context.sync();
|
|
```
|
|
|
|
#### Creating Shapes
|
|
```typescript
|
|
const shape = slide.shapes.addGeometricShape("Rectangle");
|
|
shape.left = 100;
|
|
shape.top = 100;
|
|
shape.height = 50;
|
|
shape.width = 50;
|
|
await context.sync();
|
|
```
|
|
|
|
## Status System
|
|
|
|
The application includes a status system that provides feedback to users:
|
|
|
|
- **Success**: Operation completed successfully
|
|
- **Warning**: Operation completed with concerns
|
|
- **Error**: Operation failed
|
|
- **Processing**: Shows a spinner while operations are in progress
|
|
|
|
Use the status context in your components:
|
|
```typescript
|
|
const {
|
|
statusMessage,
|
|
setStatusMessage,
|
|
statusType,
|
|
setStatusType,
|
|
isProcessing,
|
|
setIsProcessing
|
|
} = useStatusContext();
|
|
```
|
|
|
|
## Build and Deployment
|
|
|
|
### Development Build
|
|
```bash
|
|
npm run build:dev
|
|
```
|
|
|
|
### Production Build
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
### Manifest Validation
|
|
```bash
|
|
npm run validate
|
|
```
|
|
|
|
This validates the manifest.xml file against the Office Add-in schema.
|
|
|
|
## Testing
|
|
|
|
Currently, the project doesn't have automated tests. This is an area for future improvement.
|
|
|
|
Recommended testing approach:
|
|
1. Manual testing in PowerPoint
|
|
2. Implementation of unit tests for individual utilities
|
|
3. Integration tests for PowerPoint API interactions
|
|
|
|
## Performance Considerations
|
|
|
|
### Optimizing context.sync() calls
|
|
|
|
A key performance optimization is to batch context.sync() calls:
|
|
|
|
```typescript
|
|
// BAD: Calling context.sync() in a loop
|
|
for (let i = 0; i < shapes.items.length; i++) {
|
|
shapes.items[i].load("name");
|
|
await context.sync(); // Slow! One network roundtrip per shape
|
|
if (shapes.items[i].name === "Target") {
|
|
// Do something
|
|
}
|
|
}
|
|
|
|
// GOOD: Batching context.sync() calls
|
|
// Load all properties at once
|
|
for (let i = 0; i < shapes.items.length; i++) {
|
|
shapes.items[i].load("name");
|
|
}
|
|
await context.sync(); // Single network roundtrip for all shapes
|
|
|
|
// Process the data locally
|
|
for (let i = 0; i < shapes.items.length; i++) {
|
|
if (shapes.items[i].name === "Target") {
|
|
// Do something
|
|
}
|
|
}
|
|
```
|
|
|
|
Additional performance tips:
|
|
- Use memoization for expensive calculations
|
|
- Ensure proper cleanup of event listeners
|
|
- Use the ActionButton component for consistent loading states
|
|
- Consider using Web Workers for heavy computations
|
|
|
|
## Common Issues and Solutions
|
|
|
|
### Add-in not loading in PowerPoint
|
|
- Verify the development server is running
|
|
- Check for certificate errors in the browser console
|
|
- Validate the manifest.xml file
|
|
|
|
### PowerPoint API errors
|
|
- Ensure correct API version is being used
|
|
- Check the sequence of operations (some operations require specific order)
|
|
- Verify selections exist before operating on them
|
|
|
|
## Best Practices
|
|
|
|
1. **Error Handling**: Always use try/catch blocks with PowerPoint API calls and use proper types (see `office-types.ts`)
|
|
2. **User Feedback**: Provide clear status messages for all operations using the StatusContext
|
|
3. **Accessibility**: Ensure all UI elements have proper ARIA attributes and support keyboard navigation
|
|
4. **Theme Support**: Use Fluent UI theme tokens for consistent theming
|
|
5. **Code Organization**: Keep component files focused on a single responsibility
|
|
6. **Performance**: Batch context.sync() calls and avoid calling them inside loops
|
|
7. **Reusability**: Use custom hooks for common operations and shared components like ActionButton and Section
|
|
8. **Type Safety**: Avoid using "any" type and leverage TypeScript's static typing
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Make your changes
|
|
4. Submit a pull request with a clear description of the changes
|
|
|
|
## Resources
|
|
|
|
- [Office Add-ins Documentation](https://docs.microsoft.com/en-us/office/dev/add-ins/)
|
|
- [Office.js API Reference](https://docs.microsoft.com/en-us/javascript/api/overview/office)
|
|
- [Fluent UI Documentation](https://developer.microsoft.com/en-us/fluentui)
|
|
- [React Documentation](https://reactjs.org/docs/getting-started.html)
|