Files
powerpoint-toolbox/docs/DEVELOPERS.md
T

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)