mirror of
https://github.com/kaythomas0/noisedash.git
synced 2025-11-12 03:16:20 +00:00
Add profile import and export
This commit is contained in:
@@ -77,6 +77,66 @@ router.post('/profiles', (req, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.post('/profiles/import', (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
|
||||||
|
let profileID = 0
|
||||||
|
|
||||||
|
db.serialize(() => {
|
||||||
|
db.run(`INSERT INTO profiles (
|
||||||
|
name,
|
||||||
|
user,
|
||||||
|
timer_enabled,
|
||||||
|
duration,
|
||||||
|
volume,
|
||||||
|
noise_color,
|
||||||
|
filter_enabled,
|
||||||
|
filter_type,
|
||||||
|
filter_cutoff,
|
||||||
|
lfo_filter_cutoff_enabled,
|
||||||
|
lfo_filter_cutoff_frequency,
|
||||||
|
lfo_filter_cutoff_low,
|
||||||
|
lfo_filter_cutoff_high,
|
||||||
|
tremolo_enabled,
|
||||||
|
tremolo_frequency,
|
||||||
|
tremolo_depth)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
||||||
|
req.body.name,
|
||||||
|
req.user.id,
|
||||||
|
req.body.isTimerEnabled ? 1 : 0,
|
||||||
|
req.body.duration,
|
||||||
|
req.body.volume,
|
||||||
|
req.body.noiseColor,
|
||||||
|
req.body.isFilterEnabled ? 1 : 0,
|
||||||
|
req.body.filterType,
|
||||||
|
req.body.filterCutoff,
|
||||||
|
req.body.isLFOFilterCutoffEnabled ? 1 : 0,
|
||||||
|
req.body.lfoFilterCutoffFrequency,
|
||||||
|
req.body.lfoFilterCutoffLow,
|
||||||
|
req.body.lfoFilterCutoffHigh,
|
||||||
|
req.body.isTremoloEnabled ? 1 : 0,
|
||||||
|
req.body.tremoloFrequency,
|
||||||
|
req.body.tremoloDepth
|
||||||
|
],
|
||||||
|
function (err) {
|
||||||
|
if (err) {
|
||||||
|
logger.error(err)
|
||||||
|
if (err.code === 'SQLITE_CONSTRAINT') {
|
||||||
|
return res.sendStatus(409)
|
||||||
|
} else {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profileID = this.lastID
|
||||||
|
|
||||||
|
return res.json({ id: profileID })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
router.put('/profiles/:profileId', (req, res) => {
|
router.put('/profiles/:profileId', (req, res) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
|
|||||||
@@ -123,6 +123,149 @@
|
|||||||
</v-card>
|
</v-card>
|
||||||
</v-form>
|
</v-form>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
|
<v-dialog
|
||||||
|
v-model="profileMoreDialog"
|
||||||
|
max-width="600px"
|
||||||
|
>
|
||||||
|
<template v-slot:activator="{ on, attrs }">
|
||||||
|
<v-btn
|
||||||
|
v-bind="attrs"
|
||||||
|
class="mx-3 my-3"
|
||||||
|
:disabled="playDisabled"
|
||||||
|
v-on="on"
|
||||||
|
>
|
||||||
|
More...
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>
|
||||||
|
<span class="text-h5">More Profile Options</span>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-list-item-group>
|
||||||
|
<v-list-item
|
||||||
|
@click="openImportDialog"
|
||||||
|
>
|
||||||
|
<v-list-item-icon>
|
||||||
|
<v-icon>mdi-file-import</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title>
|
||||||
|
Import Profile
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item
|
||||||
|
@click="openExportDialog"
|
||||||
|
>
|
||||||
|
<v-list-item-icon>
|
||||||
|
<v-icon>mdi-file-export</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title>
|
||||||
|
Export Profile
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list-item-group>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer />
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
@click="profileMoreDialog = false"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
|
||||||
|
<v-dialog
|
||||||
|
v-model="importDialog"
|
||||||
|
max-width="600px"
|
||||||
|
>
|
||||||
|
<v-form
|
||||||
|
ref="importForm"
|
||||||
|
v-model="isImportValid"
|
||||||
|
>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>
|
||||||
|
<span class="text-h5">Import Profile</span>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-file-input
|
||||||
|
v-model="importedProfile"
|
||||||
|
accept=".json"
|
||||||
|
label="Upload a profile file!"
|
||||||
|
:rules="[rules.required()]"
|
||||||
|
/>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer />
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
@click="importDialog = false"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
:disabled="!isImportValid"
|
||||||
|
@click="importProfile"
|
||||||
|
>
|
||||||
|
Import
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-form>
|
||||||
|
</v-dialog>
|
||||||
|
|
||||||
|
<v-dialog
|
||||||
|
v-model="exportDialog"
|
||||||
|
max-width="600px"
|
||||||
|
>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>
|
||||||
|
<span class="text-h5">Export Profile</span>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-select
|
||||||
|
v-model="exportedProfile"
|
||||||
|
:items="profileItems"
|
||||||
|
return-object
|
||||||
|
label="Profiles"
|
||||||
|
class="mx-3 mb-5"
|
||||||
|
/>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer />
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
@click="exportDialog = false"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
@click="exportProfile"
|
||||||
|
>
|
||||||
|
Export
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ export default {
|
|||||||
profileDialog: false,
|
profileDialog: false,
|
||||||
profileName: '',
|
profileName: '',
|
||||||
isProfileValid: false,
|
isProfileValid: false,
|
||||||
|
profileMoreDialog: false,
|
||||||
|
importDialog: false,
|
||||||
|
isImportValid: false,
|
||||||
|
exportDialog: false,
|
||||||
|
importedProfile: null,
|
||||||
|
exportedProfile: {},
|
||||||
infoSnackbar: false,
|
infoSnackbar: false,
|
||||||
infoSnackbarText: '',
|
infoSnackbarText: '',
|
||||||
playDisabled: false,
|
playDisabled: false,
|
||||||
@@ -213,6 +219,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.selectedProfile = this.profileItems.find(p => p.id === profileId)
|
this.selectedProfile = this.profileItems.find(p => p.id === profileId)
|
||||||
}
|
}
|
||||||
|
this.exportedProfile = this.profileItems[0]
|
||||||
this.loadProfile()
|
this.loadProfile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,6 +318,10 @@ export default {
|
|||||||
this.loadedSamples = profile.samples
|
this.loadedSamples = profile.samples
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.errorSnackbarText = 'Error Loading Profile'
|
||||||
|
this.errorSnackbar = true
|
||||||
|
})
|
||||||
},
|
},
|
||||||
deleteProfile () {
|
deleteProfile () {
|
||||||
this.$http.delete('/profiles/'.concat(this.selectedProfile.id))
|
this.$http.delete('/profiles/'.concat(this.selectedProfile.id))
|
||||||
@@ -403,6 +414,102 @@ export default {
|
|||||||
if (this.$refs.uploadSampleForm) {
|
if (this.$refs.uploadSampleForm) {
|
||||||
this.$refs.uploadSampleForm.reset()
|
this.$refs.uploadSampleForm.reset()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
openImportDialog () {
|
||||||
|
this.profileMoreDialog = false
|
||||||
|
this.importDialog = true
|
||||||
|
},
|
||||||
|
openExportDialog () {
|
||||||
|
this.profileMoreDialog = false
|
||||||
|
this.exportDialog = true
|
||||||
|
},
|
||||||
|
async importProfile () {
|
||||||
|
const fileContents = await this.readFile(this.importedProfile)
|
||||||
|
const profileJSON = JSON.parse(fileContents)
|
||||||
|
|
||||||
|
this.$http.post('/profiles/import', {
|
||||||
|
name: profileJSON.name,
|
||||||
|
isTimerEnabled: profileJSON.isTimerEnabled,
|
||||||
|
duration: profileJSON.duration,
|
||||||
|
volume: profileJSON.volume,
|
||||||
|
noiseColor: profileJSON.noiseColor,
|
||||||
|
isFilterEnabled: profileJSON.isFilterEnabled,
|
||||||
|
filterType: profileJSON.filterType,
|
||||||
|
filterCutoff: profileJSON.filterCutoff,
|
||||||
|
isLFOFilterCutoffEnabled: profileJSON.isLFOFilterCutoffEnabled,
|
||||||
|
lfoFilterCutoffFrequency: profileJSON.lfoFilterCutoffFrequency,
|
||||||
|
lfoFilterCutoffLow: profileJSON.lfoFilterCutoffLow,
|
||||||
|
lfoFilterCutoffHigh: profileJSON.lfoFilterCutoffHigh,
|
||||||
|
isTremoloEnabled: profileJSON.isTremoloEnabled,
|
||||||
|
tremoloFrequency: profileJSON.tremoloFrequency,
|
||||||
|
tremoloDepth: profileJSON.tremoloDepth
|
||||||
|
}).then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.importDialog = false
|
||||||
|
this.populateProfileItems(response.data.id)
|
||||||
|
this.infoSnackbarText = 'Profile Imported and Saved'
|
||||||
|
this.infoSnackbar = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.errorSnackbarText = 'Error Saving Profile'
|
||||||
|
this.errorSnackbar = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.$refs.importForm) {
|
||||||
|
this.$refs.importForm.reset()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readFile (file) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onload = res => {
|
||||||
|
resolve(res.target.result)
|
||||||
|
}
|
||||||
|
reader.onerror = err => reject(err)
|
||||||
|
|
||||||
|
reader.readAsText(file)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
exportProfile () {
|
||||||
|
this.$http.get('/profiles/'.concat(this.exportedProfile.id))
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
const profile = response.data.profile
|
||||||
|
|
||||||
|
const profileJSON = {}
|
||||||
|
profileJSON.name = this.exportedProfile.text
|
||||||
|
profileJSON.isTimerEnabled = profile.isTimerEnabled
|
||||||
|
profileJSON.duration = profile.duration
|
||||||
|
profileJSON.volume = profile.volume
|
||||||
|
profileJSON.noiseColor = profile.noiseColor
|
||||||
|
profileJSON.isFilterEnabled = profile.isFilterEnabled
|
||||||
|
profileJSON.filterType = profile.filterType
|
||||||
|
profileJSON.filterCutoff = profile.filterCutoff
|
||||||
|
profileJSON.isLFOFilterCutoffEnabled = profile.isLFOFilterCutoffEnabled
|
||||||
|
profileJSON.lfoFilterCutoffFrequency = profile.lfoFilterCutoffFrequency
|
||||||
|
profileJSON.lfoFilterCutoffLow = profile.lfoFilterCutoffLow
|
||||||
|
profileJSON.lfoFilterCutoffHigh = profile.lfoFilterCutoffHigh
|
||||||
|
profileJSON.isTremoloEnabled = profile.isTremoloEnabled
|
||||||
|
profileJSON.tremoloFrequency = profile.tremoloFrequency
|
||||||
|
profileJSON.tremoloDepth = profile.tremoloDepth
|
||||||
|
|
||||||
|
const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(profileJSON))
|
||||||
|
const downloadAnchorNode = document.createElement('a')
|
||||||
|
downloadAnchorNode.setAttribute('href', dataStr)
|
||||||
|
downloadAnchorNode.setAttribute('download', profileJSON.name + '.json')
|
||||||
|
document.body.appendChild(downloadAnchorNode) // required for firefox
|
||||||
|
downloadAnchorNode.click()
|
||||||
|
downloadAnchorNode.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.errorSnackbarText = 'Error Loading Profile'
|
||||||
|
this.errorSnackbar = true
|
||||||
|
})
|
||||||
|
|
||||||
|
this.exportDialog = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user