Skip to content

Commit b31971e

Browse files
authored
Merge pull request #153 from espadonne/main
DAWn_EE and studio pages
2 parents 7132474 + 3d9e865 commit b31971e

216 files changed

Lines changed: 86378 additions & 443 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,18 @@ yarn-error.log*
3333
# vercel
3434
.vercel
3535

36+
# audio files for @mfwolffe DAW testing
37+
/public/sample_audio
3638
# Sentry Config File
3739
.env.sentry-build-plugin
40+
41+
/public/sample_audio/
42+
43+
# audio files for @mfwolffe DAW testing
44+
/public/sample_audio
45+
46+
# asdf things
47+
.tool-versions
48+
49+
# vscode things
50+
.vscode/settings.json

.vscode/settings.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

DAW-CRUFT.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# DAW Cruft Analysis & Cleanup Checklist
2+
3+
*Generated on August 20, 2025*
4+
5+
This document identifies orphaned, vestigial, and redundant components within the DAW system that can be safely removed or refactored to improve codebase maintainability.
6+
7+
## Safe to Delete Immediately
8+
9+
### Orphaned Test/Debug Components
10+
- [ ] **`components/audio/DAW/Multitrack/TrackDebug.js`**
11+
- **Status**: Complete orphan
12+
- **Justification**: Not imported anywhere in the codebase
13+
- **Context**: Appears to be a debugging component left over from development
14+
- **Risk**: None - no references found
15+
16+
- [ ] **`components/audio/DAW/Multitrack/SimpleWaveformTest.js`**
17+
- **Status**: Complete orphan
18+
- **Justification**: Not imported or referenced anywhere
19+
- **Context**: Test component with hardcoded `console.log` statements
20+
- **Risk**: None - clearly a development artifact
21+
22+
- [ ] **`components/audio/DAW/Multitrack/VirtualPiano.js`**
23+
- **Status**: Complete orphan
24+
- **Justification**: Not imported anywhere, potentially redundant with existing piano components
25+
- **Context**: Appears to be an alternate implementation or abandoned feature
26+
- **Risk**: None - no usage found
27+
28+
### Deprecated Effect System
29+
- [ ] **`components/audio/DAW/Effects/index.js`**
30+
- **Status**: Deprecated placeholder
31+
- **Justification**: File contains comment "This file is kept for backward compatibility" and returns `null`
32+
- **Context**: Old effects system replaced by `EffectsRack.js`
33+
- **Risk**: None - explicitly marked as deprecated
34+
35+
## Investigate Before Deleting
36+
37+
### Legacy DAW Implementation
38+
- [ ] **`components/audio/daw-old/dawStd.js`**
39+
- **Status**: Appears orphaned but needs verification
40+
- **Justification**: `DawStd` component not imported anywhere, but file is substantial (278 lines)
41+
- **Context**: Legacy single-track DAW implementation, replaced by new DAW system
42+
- **Risk**: Low - but verify no dynamic imports or runtime references
43+
- **Action**: Search for any string references to "dawStd" or "DawStd" in runtime code
44+
45+
- [ ] **`components/audio/daw-old/control.js`**
46+
- **Status**: Dependent on dawStd.js
47+
- **Justification**: Only imported by `dawStd.js` - if dawStd is removed, this becomes orphaned
48+
- **Context**: UI controls for legacy DAW implementation
49+
- **Risk**: Low - remove after confirming dawStd.js removal
50+
51+
### Potentially Unused Canvas Component
52+
- [ ] **`components/audio/DAW/Multitrack/TrackWaveCanvas.jsx`**
53+
- **Status**: Not imported anywhere
54+
- **Justification**: No import statements found for this component
55+
- **Context**: Might be an alternate waveform rendering implementation
56+
- **Risk**: Medium - could be used dynamically or be a newer implementation
57+
- **Action**: Check git history and verify if this is a newer/alternate implementation
58+
59+
## Refactor Candidates
60+
61+
### Extract Dependencies from Legacy Code
62+
- [ ] **Extract `MinimapContainer` from `daw-old/common.js`**
63+
- **Status**: Still needed by current DAW
64+
- **Justification**: Used in `components/audio/DAW/Waveform.js`
65+
- **Context**: Only component from old system still in use
66+
- **Action**: Move to its own file, update import in `Waveform.js`
67+
- **Risk**: Low - straightforward extraction
68+
69+
- [ ] **Extract `HelpModal` from `daw-old/dawHelp.js`**
70+
- **Status**: Still needed by current DAW
71+
- **Justification**: Used in `components/audio/DAW/index.js`
72+
- **Context**: Help system shared between old and new DAW
73+
- **Action**: Move to shared location like `components/common/` or `components/DAW/`
74+
- **Risk**: Low - clean extraction
75+
76+
- [ ] **Clean up remaining `daw-old/common.js`**
77+
- **Status**: Partially used
78+
- **Justification**: After extracting `MinimapContainer`, check what else is exported/used
79+
- **Context**: Large file (290+ lines) with multiple exports, some likely unused
80+
- **Action**: Remove unused exports after extracting needed components
81+
- **Risk**: Medium - need to verify all exports are truly unused
82+
83+
## Questionable Components (Need Investigation)
84+
85+
### Potentially Redundant Piano Components
86+
- [ ] **`components/audio/DAW/Multitrack/PianoKeyboard.js`**
87+
- **Status**: Imported by MIDI components but might be redundant
88+
- **Justification**: Similar functionality to `VirtualPiano.js` (which is orphaned)
89+
- **Context**: Part of MIDI track functionality
90+
- **Action**: Verify this is the "correct" piano implementation vs VirtualPiano
91+
- **Risk**: Medium - used in MIDI system
92+
93+
### MIDI/Pattern System Components
94+
- [ ] **Verify usage of Pattern system**
95+
- **Components**: `PatternLibrary.js`, `PatternClipRenderer.js`
96+
- **Status**: Used by `MIDITrack.js` but might be incomplete feature
97+
- **Context**: MIDI pattern/clip system that might not be fully implemented
98+
- **Action**: Test MIDI functionality to verify these are working features
99+
- **Risk**: High - could break MIDI functionality
100+
101+
## Impact Analysis
102+
103+
### Files Currently Safe to Delete
104+
- **Count**: 4 files
105+
- **Total LOC**: ~200-300 lines (estimated)
106+
- **Dependencies**: None
107+
108+
### Files Requiring Investigation
109+
- **Count**: 6-8 files
110+
- **Total LOC**: ~500-800 lines (estimated)
111+
- **Dependencies**: Some interdependent (dawStd.js → control.js)
112+
113+
### Cleanup Benefits
114+
- **Code Reduction**: Potentially 700-1100 lines of dead code
115+
- **Maintenance**: Reduced cognitive load when navigating DAW components
116+
- **Clarity**: Cleaner import structure and component organization
117+
- **Build Size**: Marginal reduction in bundle size
118+
119+
## Warnings & Considerations
120+
121+
1. **Runtime References**: Some components might be referenced via string lookups or dynamic imports
122+
2. **Feature Completeness**: Some "orphaned" components might be newer implementations not yet integrated
123+
3. **Git History**: Check component creation dates and recent commits before deletion
124+
4. **User Impact**: Verify no user-facing features depend on questionable components
125+
5. **Testing**: Ensure full DAW functionality testing after any removals
126+
127+
## Recommended Cleanup Order
128+
129+
1. **Phase 1**: Delete confirmed orphans (TrackDebug, SimpleWaveformTest, VirtualPiano, Effects/index.js)
130+
2. **Phase 2**: Extract and relocate still-needed components from daw-old
131+
3. **Phase 3**: Investigate and remove legacy DAW implementation (dawStd.js, control.js)
132+
4. **Phase 4**: Clean up remaining daw-old files
133+
5. **Phase 5**: Investigate questionable multitrack components
134+
135+
## Testing Checklist
136+
137+
After any deletions, verify:
138+
- [ ] Single-track DAW functionality (waveform, effects, transport)
139+
- [ ] Multi-track DAW functionality (track management, mixing)
140+
- [ ] MIDI recording and playback
141+
- [ ] Effects rack functionality
142+
- [ ] Help system accessibility
143+
- [ ] Audio import/export
144+
- [ ] Project save/load (if implemented)
145+
146+
---
147+
148+
*Note: This analysis was performed via static code analysis. Dynamic usage patterns and runtime behavior should be verified before making changes.*

actions.js

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,18 @@ export function postRecording({
533533
} = getState();
534534

535535
dispatch(beginUpload(submissionId));
536-
// let body = ''
536+
537+
// Try to get activity log from window global if composition not provided
538+
let activityLogContent = composition;
539+
if (!activityLogContent && typeof window !== 'undefined' && window.__PENDING_ACTIVITY_LOG__) {
540+
activityLogContent = window.__PENDING_ACTIVITY_LOG__;
541+
console.log('📊 Using activity log from window global for submission content');
542+
}
543+
537544
let bodyObj = { content: 'N/A for Perform submissions' };
538-
if (composition) {
539-
bodyObj = { content: composition };
545+
if (activityLogContent) {
546+
bodyObj = { content: activityLogContent };
547+
console.log('📊 Setting submission content with activity log');
540548
}
541549

542550
bodyObj.index = index;
@@ -555,14 +563,47 @@ export function postRecording({
555563
.then(assertResponse)
556564
.then((res) => res.json())
557565
.then((submission) => {
566+
// Create FormData for the file upload
567+
// Django/DRF typically expects 'file' as the field name
568+
const formData = new FormData();
569+
570+
// Determine filename extension from MIME type
571+
let extension = 'webm';
572+
if (audio.type) {
573+
if (audio.type.includes('webm')) extension = 'webm';
574+
else if (audio.type.includes('ogg')) extension = 'ogg';
575+
else if (audio.type.includes('wav')) extension = 'wav';
576+
else if (audio.type.includes('mp4')) extension = 'mp4';
577+
else if (audio.type.includes('mpeg') || audio.type.includes('mp3')) extension = 'mp3';
578+
}
579+
580+
// Append the audio file with 'file' as the field name (standard Django field name)
581+
formData.append('file', audio, `recording.${extension}`);
582+
583+
console.log('📊 Uploading audio:', {
584+
fieldName: 'file',
585+
filename: `recording.${extension}`,
586+
type: audio.type,
587+
size: audio.size
588+
});
589+
590+
// Note: Activity log is now sent in the submission content field above,
591+
// not as a separate attachment field. Clear the window global.
592+
if (typeof window !== 'undefined' && window.__PENDING_ACTIVITY_LOG__) {
593+
console.log('📊 Activity log was already included in submission content');
594+
window.__PENDING_ACTIVITY_LOG__ = null;
595+
window.__PENDING_ACTIVITY_LOG_TIMESTAMP__ = null;
596+
}
597+
558598
fetch(
559599
`${process.env.NEXT_PUBLIC_BACKEND_HOST}/api/courses/${slug}/assignments/${assignmentId}/submissions/${submission.id}/attachments/`,
560600
{
561601
headers: {
562602
Authorization: `Token ${token}`,
603+
// Don't set Content-Type - let browser set it with multipart boundary
563604
},
564605
method: 'POST',
565-
body: audio,
606+
body: formData,
566607
},
567608
)
568609
.then(assertResponse)

api.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,62 @@ export function getAssignedPieces(assignments) {
174174
return pieces;
175175
};
176176
}
177+
178+
// ========== Activity Progress API ==========
179+
180+
export async function getActivityProgress({ slug, assignmentId }) {
181+
const endpoint = `courses/${slug}/assignments/${assignmentId}/activity-progress/`;
182+
try {
183+
const json = await makeRequest(endpoint);
184+
return json;
185+
} catch (error) {
186+
// Return null if not found (first time accessing)
187+
if (error.message.includes('404')) {
188+
return null;
189+
}
190+
throw error;
191+
}
192+
}
193+
194+
export function mutateLogActivityEvent({ slug, assignmentId }) {
195+
return async ({ operation, step, data = {} }) => {
196+
const endpoint = `courses/${slug}/assignments/${assignmentId}/activity-progress/log_event/`;
197+
const body = { operation, step, data };
198+
const json = await makeRequest(endpoint, 'POST', body);
199+
return json;
200+
};
201+
}
202+
203+
export function mutateSubmitActivityStep({ slug, assignmentId }) {
204+
return async ({ questionResponses = {}, step = null }) => {
205+
const endpoint = `courses/${slug}/assignments/${assignmentId}/activity-progress/submit_step/`;
206+
const body = { question_responses: questionResponses };
207+
if (step !== null) {
208+
body.step = step;
209+
}
210+
const json = await makeRequest(endpoint, 'POST', body);
211+
return json;
212+
};
213+
}
214+
215+
export function mutateSaveQuestionResponse({ slug, assignmentId }) {
216+
return async ({ questionId, response }) => {
217+
const endpoint = `courses/${slug}/assignments/${assignmentId}/activity-progress/save_response/`;
218+
const body = { question_id: questionId, response };
219+
const json = await makeRequest(endpoint, 'POST', body);
220+
return json;
221+
};
222+
}
223+
224+
export function mutateSaveAudioState({ slug, assignmentId }) {
225+
return async ({ audioUrl, editHistory, metadata }) => {
226+
const endpoint = `courses/${slug}/assignments/${assignmentId}/activity-progress/save_audio_state/`;
227+
const body = {
228+
audio_url: audioUrl,
229+
edit_history: editHistory,
230+
metadata,
231+
};
232+
const json = await makeRequest(endpoint, 'POST', body);
233+
return json;
234+
};
235+
}

0 commit comments

Comments
 (0)