mirror of
https://github.com/kaythomas0/noisedash.git
synced 2025-11-11 19:06:20 +00:00
Add sample support, re-organize repo
This commit is contained in:
9
package-lock.json
generated
9
package-lock.json
generated
@@ -5403,6 +5403,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint-plugin-html": {
|
||||||
|
"version": "6.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.1.2.tgz",
|
||||||
|
"integrity": "sha512-bhBIRyZFqI4EoF12lGDHAmgfff8eLXx6R52/K3ESQhsxzCzIE6hdebS7Py651f7U3RBotqroUnC3L29bR7qJWQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"htmlparser2": "^6.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"eslint-plugin-import": {
|
"eslint-plugin-import": {
|
||||||
"version": "2.23.4",
|
"version": "2.23.4",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz",
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
"@vue/eslint-config-standard": "^5.1.2",
|
"@vue/eslint-config-standard": "^5.1.2",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
|
"eslint-plugin-html": "^6.1.2",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ module.exports = function () {
|
|||||||
hashed_password BLOB,
|
hashed_password BLOB,
|
||||||
salt BLOB,
|
salt BLOB,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
is_admin INTEGER)`
|
is_admin INTEGER,
|
||||||
|
dark_mode INTEGER,
|
||||||
|
can_upload INTEGER)`
|
||||||
)
|
)
|
||||||
|
|
||||||
db.run(`CREATE TABLE IF NOT EXISTS profiles (
|
db.run(`CREATE TABLE IF NOT EXISTS profiles (
|
||||||
@@ -35,7 +37,6 @@ module.exports = function () {
|
|||||||
db.run(`CREATE TABLE IF NOT EXISTS samples (
|
db.run(`CREATE TABLE IF NOT EXISTS samples (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
name TEXT UNIQUE,
|
name TEXT UNIQUE,
|
||||||
volume INTEGER,
|
|
||||||
user INTEGER,
|
user INTEGER,
|
||||||
FOREIGN KEY(user) REFERENCES users(id))`
|
FOREIGN KEY(user) REFERENCES users(id))`
|
||||||
)
|
)
|
||||||
@@ -44,6 +45,7 @@ module.exports = function () {
|
|||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
profile INTEGER,
|
profile INTEGER,
|
||||||
sample INTEGER,
|
sample INTEGER,
|
||||||
|
volume INTEGER,
|
||||||
FOREIGN KEY(profile) REFERENCES profiles(id),
|
FOREIGN KEY(profile) REFERENCES profiles(id),
|
||||||
FOREIGN KEY(sample) REFERENCES samples(id))`
|
FOREIGN KEY(sample) REFERENCES samples(id))`
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,27 +47,26 @@ router.post('/profiles', (req, res) => {
|
|||||||
],
|
],
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
if (err.code === 'SQLITE_CONSTRAINT') {
|
||||||
|
return res.sendStatus(409)
|
||||||
|
} else {
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
profileID = this.lastID
|
profileID = this.lastID
|
||||||
|
|
||||||
req.body.samples.forEach(s => {
|
req.body.samples.forEach(s => {
|
||||||
db.run('INSERT INTO profiles_samples (profile, sample) VALUES (?, ?)', [
|
db.run('INSERT INTO profiles_samples (profile, sample, volume) VALUES (?, ?, ?)', [
|
||||||
profileID,
|
profileID,
|
||||||
s.id
|
s.id,
|
||||||
|
s.volume
|
||||||
],
|
],
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
db.run('UPDATE samples SET volume = ? WHERE id = ?', [s.volume, s.id], (err) => {
|
|
||||||
if (err) {
|
|
||||||
return res.sendStatus(500)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.json({ id: profileID })
|
return res.json({ id: profileID })
|
||||||
@@ -75,6 +74,88 @@ router.post('/profiles', (req, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.put('/profiles/:profileId', (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.serialize(() => {
|
||||||
|
db.get('SELECT user FROM profiles WHERE id = ?', [req.params.profileId], (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.user.toString() !== req.user.id) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
db.run(`UPDATE profiles SET
|
||||||
|
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 = ?
|
||||||
|
WHERE 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,
|
||||||
|
req.params.profileId
|
||||||
|
],
|
||||||
|
(err) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.serialize(() => {
|
||||||
|
db.run('DELETE FROM profiles_samples WHERE profile = ?', [
|
||||||
|
req.params.profileId
|
||||||
|
],
|
||||||
|
(err) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
req.body.samples.forEach(s => {
|
||||||
|
db.run('INSERT INTO profiles_samples (profile, sample, volume) VALUES (?, ?, ?)', [
|
||||||
|
req.params.profileId,
|
||||||
|
s.id,
|
||||||
|
s.volume
|
||||||
|
],
|
||||||
|
(err) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return res.sendStatus(200)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
router.post('/profiles/default', (req, res) => {
|
router.post('/profiles/default', (req, res) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
@@ -117,13 +198,13 @@ router.get('/profiles', (req, res) => {
|
|||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
const profiles = []
|
|
||||||
|
|
||||||
db.all('SELECT id, name FROM profiles WHERE user = ?', [req.user.id], (err, rows) => {
|
db.all('SELECT id, name FROM profiles WHERE user = ?', [req.user.id], (err, rows) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const profiles = []
|
||||||
|
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
const profile = {}
|
const profile = {}
|
||||||
|
|
||||||
@@ -142,8 +223,6 @@ router.get('/profiles/:profileId', (req, res) => {
|
|||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
const profile = {}
|
|
||||||
|
|
||||||
db.serialize(() => {
|
db.serialize(() => {
|
||||||
db.get(`SELECT
|
db.get(`SELECT
|
||||||
name,
|
name,
|
||||||
@@ -164,6 +243,7 @@ router.get('/profiles/:profileId', (req, res) => {
|
|||||||
tremolo_depth as tremoloDepth
|
tremolo_depth as tremoloDepth
|
||||||
FROM profiles WHERE id = ?`, [req.params.profileId], (err, row) => {
|
FROM profiles WHERE id = ?`, [req.params.profileId], (err, row) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +251,8 @@ router.get('/profiles/:profileId', (req, res) => {
|
|||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const profile = {}
|
||||||
|
|
||||||
profile.name = row.name
|
profile.name = row.name
|
||||||
profile.isTimerEnabled = row.isTimerEnabled === 1
|
profile.isTimerEnabled = row.isTimerEnabled === 1
|
||||||
profile.duration = row.duration
|
profile.duration = row.duration
|
||||||
@@ -187,24 +269,34 @@ router.get('/profiles/:profileId', (req, res) => {
|
|||||||
profile.tremoloFrequency = row.tremoloFrequency
|
profile.tremoloFrequency = row.tremoloFrequency
|
||||||
profile.tremoloDepth = row.tremoloDepth
|
profile.tremoloDepth = row.tremoloDepth
|
||||||
|
|
||||||
const sampleIds = []
|
|
||||||
|
|
||||||
db.all('SELECT sample FROM profiles_samples WHERE profile = ?', [req.params.profileId], (err, rows) => {
|
db.all('SELECT sample FROM profiles_samples WHERE profile = ?', [req.params.profileId], (err, rows) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sampleQueryArgs = []
|
||||||
|
|
||||||
|
sampleQueryArgs.push(req.params.profileId)
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
sampleQueryArgs.push(row.sample)
|
||||||
|
})
|
||||||
|
|
||||||
|
db.all(`SELECT samples.id, name, profiles_samples.volume
|
||||||
|
FROM samples
|
||||||
|
INNER JOIN profiles_samples
|
||||||
|
ON profiles_samples.sample = samples.id
|
||||||
|
AND profiles_samples.profile = ?
|
||||||
|
WHERE samples.id IN ( ` +
|
||||||
|
sampleQueryArgs.map(() => { return '?' }).join(',') + ' )', sampleQueryArgs, (err, rows) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
const samples = []
|
const samples = []
|
||||||
|
|
||||||
rows.forEach(row => {
|
|
||||||
sampleIds.push(row.sample)
|
|
||||||
})
|
|
||||||
|
|
||||||
db.all('SELECT id, name, volume FROM samples WHERE id IN ( ' + sampleIds.map(() => { return '?' }).join(',') + ' )', sampleIds, (err, rows) => {
|
|
||||||
if (err) {
|
|
||||||
return res.sendStatus(500)
|
|
||||||
}
|
|
||||||
|
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
const sample = {}
|
const sample = {}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ const config = require('config')
|
|||||||
const multer = require('multer')
|
const multer = require('multer')
|
||||||
const storage = multer.diskStorage({
|
const storage = multer.diskStorage({
|
||||||
destination: config.get('Server.sampleUploadPath'),
|
destination: config.get('Server.sampleUploadPath'),
|
||||||
filename: function (req, file, cb) {
|
filename: (req, file, cb) => {
|
||||||
cb(null, req.body.name)
|
cb(null, req.user.id + '_' + req.body.name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const upload = multer({ storage: storage })
|
const upload = multer({ storage: storage })
|
||||||
@@ -16,18 +16,34 @@ router.post('/samples', upload.single('sample'), (req, res, next) => {
|
|||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.run('INSERT INTO samples (name, volume, user) VALUES (?, ?, ?)', [
|
db.serialize(() => {
|
||||||
|
db.get('SELECT can_upload FROM users WHERE id = ?', [req.user.id], (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.can_upload === 0) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
db.run('INSERT INTO samples (name, user) VALUES (?, ?)', [
|
||||||
req.body.name,
|
req.body.name,
|
||||||
0,
|
|
||||||
req.user.id
|
req.user.id
|
||||||
],
|
],
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
|
if (err.code === 'SQLITE_CONSTRAINT') {
|
||||||
|
return res.sendStatus(409)
|
||||||
|
} else {
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return res.sendStatus(200)
|
return res.sendStatus(200)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/samples', (req, res) => {
|
router.get('/samples', (req, res) => {
|
||||||
@@ -37,8 +53,9 @@ router.get('/samples', (req, res) => {
|
|||||||
|
|
||||||
const samples = []
|
const samples = []
|
||||||
|
|
||||||
db.all('SELECT id, name, volume FROM samples WHERE user = ?', [req.user.id], (err, rows) => {
|
db.all('SELECT id, name FROM samples WHERE user = ?', [req.user.id], (err, rows) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +64,7 @@ router.get('/samples', (req, res) => {
|
|||||||
|
|
||||||
sample.id = row.id
|
sample.id = row.id
|
||||||
sample.name = row.name
|
sample.name = row.name
|
||||||
sample.volume = row.volume
|
sample.user = req.user.id
|
||||||
|
|
||||||
samples.push(sample)
|
samples.push(sample)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,17 +8,21 @@ router.get('/users/current', (req, res) => {
|
|||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.get('SELECT is_admin as isAdmin, * FROM users WHERE id = ?', [req.user.id], (err, row) => {
|
db.get('SELECT is_admin as isAdmin, dark_mode as darkMode, can_upload as canUpload, * FROM users WHERE id = ?', [req.user.id], (err, row) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = {}
|
const user = {}
|
||||||
|
|
||||||
|
if (row) {
|
||||||
user.id = row.id
|
user.id = row.id
|
||||||
user.username = row.username
|
user.username = row.username
|
||||||
user.name = row.name
|
user.name = row.name
|
||||||
user.isAdmin = row.isAdmin === 1
|
user.isAdmin = row.isAdmin === 1
|
||||||
|
user.darkMode = row.darkMode === 1
|
||||||
|
user.canUpload = row.canUpload === 1
|
||||||
|
}
|
||||||
|
|
||||||
res.json({ user: user })
|
res.json({ user: user })
|
||||||
})
|
})
|
||||||
@@ -31,7 +35,7 @@ router.get('/users', (req, res) => {
|
|||||||
|
|
||||||
const users = []
|
const users = []
|
||||||
|
|
||||||
db.all('SELECT id, username, name, is_admin as isAdmin FROM users', (err, rows) => {
|
db.all('SELECT id, username, name, is_admin as isAdmin, can_upload as canUpload FROM users', (err, rows) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
@@ -43,6 +47,7 @@ router.get('/users', (req, res) => {
|
|||||||
user.username = row.username
|
user.username = row.username
|
||||||
user.name = row.name
|
user.name = row.name
|
||||||
user.isAdmin = row.isAdmin === 1
|
user.isAdmin = row.isAdmin === 1
|
||||||
|
user.canUpload = row.canUpload === 1
|
||||||
|
|
||||||
users.push(user)
|
users.push(user)
|
||||||
})
|
})
|
||||||
@@ -58,12 +63,15 @@ router.post('/users', (req, res) => {
|
|||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.run('INSERT INTO users (username, hashed_password, salt, name, is_admin) VALUES (?, ?, ?, ?, ?)', [
|
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
||||||
req.body.username,
|
req.body.username,
|
||||||
hashedPassword,
|
hashedPassword,
|
||||||
salt,
|
salt,
|
||||||
req.body.name,
|
req.body.name,
|
||||||
req.body.isAdmin
|
req.body.isAdmin,
|
||||||
|
req.body.darkMode,
|
||||||
|
req.body.canUpload
|
||||||
], function (err) {
|
], function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.code === 'SQLITE_CONSTRAINT') {
|
if (err.code === 'SQLITE_CONSTRAINT') {
|
||||||
@@ -89,7 +97,7 @@ router.post('/users', (req, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.patch('/users/:userId', (req, res) => {
|
router.patch('/users/admin/:userId', (req, res) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
@@ -115,6 +123,48 @@ router.patch('/users/:userId', (req, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.patch('/users/upload/:userId', (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.serialize(() => {
|
||||||
|
db.get('SELECT is_admin FROM users WHERE id = ?', [req.user.id], (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.is_admin === 0) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
db.run('UPDATE users SET can_upload = ? WHERE id = ?', [req.body.canUpload ? 1 : 0, req.params.userId], (err) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
} else {
|
||||||
|
return res.sendStatus(200)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
router.patch('/users/dark-mode', (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.serialize(() => {
|
||||||
|
db.run('UPDATE users SET dark_mode = ? WHERE id = ?', [req.body.darkMode ? 1 : 0, req.user.id], (err) => {
|
||||||
|
if (err) {
|
||||||
|
return res.sendStatus(500)
|
||||||
|
} else {
|
||||||
|
return res.sendStatus(200)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
router.delete('/users/:userId', (req, res) => {
|
router.delete('/users/:userId', (req, res) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
|
|||||||
@@ -1,54 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row class="text-left">
|
<v-row class="text-center">
|
||||||
<v-col class="mb-5">
|
<v-col class="mb-5">
|
||||||
<h1 class="display-2 font-weight-bold mb-3">
|
<h1 class="display-2 font-weight-bold mb-3">
|
||||||
Admin Dashboard
|
Admin Dashboard
|
||||||
</h1>
|
</h1>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row class="text-center">
|
||||||
|
<v-col class="mb-5">
|
||||||
|
<h2 class="headline font-weight-bold">
|
||||||
|
Users
|
||||||
|
</h2>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<v-simple-table>
|
<v-row
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="text-left">
|
|
||||||
ID
|
|
||||||
</th>
|
|
||||||
<th class="text-left">
|
|
||||||
Username
|
|
||||||
</th>
|
|
||||||
<th class="text-left">
|
|
||||||
Is Admin
|
|
||||||
</th>
|
|
||||||
<th class="text-left">
|
|
||||||
Delete User
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="user in users"
|
v-for="user in users"
|
||||||
:key="user.username"
|
:key="user.username"
|
||||||
>
|
>
|
||||||
<td>{{ user.id }}</td>
|
<v-container>
|
||||||
<td>{{ user.username }}</td>
|
<v-row
|
||||||
<td>
|
justify="center"
|
||||||
|
>
|
||||||
|
ID: {{ user.id }}
|
||||||
|
</v-row>
|
||||||
|
<v-row
|
||||||
|
justify="center"
|
||||||
|
>
|
||||||
|
Username: {{ user.username }}
|
||||||
|
</v-row>
|
||||||
|
<v-row
|
||||||
|
justify="center"
|
||||||
|
>
|
||||||
|
Name: {{ user.name }}
|
||||||
|
</v-row>
|
||||||
|
<v-row
|
||||||
|
justify="center"
|
||||||
|
>
|
||||||
<v-switch
|
<v-switch
|
||||||
v-model="user.isAdmin"
|
v-model="user.isAdmin"
|
||||||
:label="`${user.isAdmin ? 'True' : 'False'}`"
|
:label="`${user.isAdmin ? 'Admin' : 'Not Admin'}`"
|
||||||
@change="updateUser(user.id, user.isAdmin); snackbar = true"
|
:disabled="user.id === currentUser.id"
|
||||||
|
@change="updateUserAdmin(user.id, user.isAdmin); snackbar = true"
|
||||||
/>
|
/>
|
||||||
</td>
|
</v-row>
|
||||||
<td>
|
<v-row
|
||||||
|
justify="center"
|
||||||
|
>
|
||||||
|
<v-switch
|
||||||
|
v-model="user.canUpload"
|
||||||
|
:label="`${user.canUpload ? 'Can Upload Samples' : 'Cannot Upload Samples'}`"
|
||||||
|
:disabled="user.id === currentUser.id"
|
||||||
|
@change="updateUserUpload(user.id, user.canUpload); snackbar = true"
|
||||||
|
/>
|
||||||
|
</v-row>
|
||||||
|
<v-row
|
||||||
|
justify="center"
|
||||||
|
>
|
||||||
<v-btn
|
<v-btn
|
||||||
|
:disabled="user.id === currentUser.id"
|
||||||
@click="deleteUser(user.id)"
|
@click="deleteUser(user.id)"
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</td>
|
</v-row>
|
||||||
</tr>
|
<v-divider
|
||||||
</tbody>
|
class="mt-7"
|
||||||
</v-simple-table>
|
/>
|
||||||
|
</v-container>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
<v-snackbar
|
<v-snackbar
|
||||||
v-model="snackbar"
|
v-model="snackbar"
|
||||||
timeout="3000"
|
timeout="3000"
|
||||||
@@ -66,59 +90,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-snackbar>
|
</v-snackbar>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script src="./admin.js"></script>
|
||||||
export default {
|
|
||||||
name: 'Admin',
|
|
||||||
|
|
||||||
data: () => ({
|
|
||||||
users: [],
|
|
||||||
snackbar: false,
|
|
||||||
updateText: ''
|
|
||||||
}),
|
|
||||||
created () {
|
|
||||||
this.getUsers()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getUsers () {
|
|
||||||
this.$http.get('/users')
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.users = response.data.users
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.response)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateUser (id, isAdmin) {
|
|
||||||
this.$http.patch('/users/'.concat(id), {
|
|
||||||
isAdmin: isAdmin
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.updateText = 'User updated'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
console.error(error.response)
|
|
||||||
this.updateText = 'Error updating user'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteUser (id) {
|
|
||||||
this.$http.delete('/users/'.concat(id))
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.getUsers()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.response)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
dense
|
dense
|
||||||
>
|
>
|
||||||
<v-app-bar-nav-icon
|
<v-app-bar-nav-icon
|
||||||
@click="openDrawyer"
|
@click="drawyer = true"
|
||||||
/>
|
/>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
<v-navigation-drawer
|
<v-navigation-drawer
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
<v-switch
|
<v-switch
|
||||||
v-model="$vuetify.theme.dark"
|
v-model="$vuetify.theme.dark"
|
||||||
label="Dark Mode"
|
label="Dark Mode"
|
||||||
|
@change="toggleDarkMode"
|
||||||
/>
|
/>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list-item-group>
|
</v-list-item-group>
|
||||||
@@ -62,47 +63,4 @@
|
|||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script src="./appbar.js"></script>
|
||||||
export default {
|
|
||||||
name: 'AppBar',
|
|
||||||
|
|
||||||
data: () => ({
|
|
||||||
drawyer: false,
|
|
||||||
isAdmin: false
|
|
||||||
}),
|
|
||||||
methods: {
|
|
||||||
home () {
|
|
||||||
this.$router.push('/')
|
|
||||||
},
|
|
||||||
admin () {
|
|
||||||
this.$router.push('/admin')
|
|
||||||
},
|
|
||||||
logout () {
|
|
||||||
this.$http.get('/logout')
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.$router.push('/login')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.response)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
openDrawyer () {
|
|
||||||
this.$http.get('/users/current')
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.user.isAdmin) {
|
|
||||||
this.isAdmin = true
|
|
||||||
} else {
|
|
||||||
this.isAdmin = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
console.error(error.response)
|
|
||||||
this.isAdmin = false
|
|
||||||
})
|
|
||||||
this.drawyer = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -1,151 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-container>
|
|
||||||
<v-row class="text-center">
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-img
|
|
||||||
:src="require('../assets/logo.svg')"
|
|
||||||
class="my-3"
|
|
||||||
contain
|
|
||||||
height="200"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col class="mb-4">
|
|
||||||
<h1 class="display-2 font-weight-bold mb-3">
|
|
||||||
Welcome to Vuetify
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p class="subheading font-weight-regular">
|
|
||||||
For help and collaboration with other Vuetify developers,
|
|
||||||
<br>please join our online
|
|
||||||
<a
|
|
||||||
href="https://community.vuetifyjs.com"
|
|
||||||
target="_blank"
|
|
||||||
>Discord Community</a>
|
|
||||||
</p>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col
|
|
||||||
class="mb-5"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<h2 class="headline font-weight-bold mb-3">
|
|
||||||
What's next?
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<v-row justify="center">
|
|
||||||
<a
|
|
||||||
v-for="(next, i) in whatsNext"
|
|
||||||
:key="i"
|
|
||||||
:href="next.href"
|
|
||||||
class="subheading mx-3"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ next.text }}
|
|
||||||
</a>
|
|
||||||
</v-row>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col
|
|
||||||
class="mb-5"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<h2 class="headline font-weight-bold mb-3">
|
|
||||||
Important Links
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<v-row justify="center">
|
|
||||||
<a
|
|
||||||
v-for="(link, i) in importantLinks"
|
|
||||||
:key="i"
|
|
||||||
:href="link.href"
|
|
||||||
class="subheading mx-3"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ link.text }}
|
|
||||||
</a>
|
|
||||||
</v-row>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col
|
|
||||||
class="mb-5"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<h2 class="headline font-weight-bold mb-3">
|
|
||||||
Ecosystem
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<v-row justify="center">
|
|
||||||
<a
|
|
||||||
v-for="(eco, i) in ecosystem"
|
|
||||||
:key="i"
|
|
||||||
:href="eco.href"
|
|
||||||
class="subheading mx-3"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ eco.text }}
|
|
||||||
</a>
|
|
||||||
</v-row>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'HelloWorld',
|
|
||||||
|
|
||||||
data: () => ({
|
|
||||||
ecosystem: [
|
|
||||||
{
|
|
||||||
text: 'vuetify-loader',
|
|
||||||
href: 'https://github.com/vuetifyjs/vuetify-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'github',
|
|
||||||
href: 'https://github.com/vuetifyjs/vuetify'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'awesome-vuetify',
|
|
||||||
href: 'https://github.com/vuetifyjs/awesome-vuetify'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
importantLinks: [
|
|
||||||
{
|
|
||||||
text: 'Documentation',
|
|
||||||
href: 'https://vuetifyjs.com'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Chat',
|
|
||||||
href: 'https://community.vuetifyjs.com'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Made with Vuetify',
|
|
||||||
href: 'https://madewithvuejs.com/vuetify'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Twitter',
|
|
||||||
href: 'https://twitter.com/vuetifyjs'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Articles',
|
|
||||||
href: 'https://medium.com/vuetify'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
whatsNext: [
|
|
||||||
{
|
|
||||||
text: 'Explore components',
|
|
||||||
href: 'https://vuetifyjs.com/components/api-explorer'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Select a layout',
|
|
||||||
href: 'https://vuetifyjs.com/getting-started/pre-made-layouts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Frequently Asked Questions',
|
|
||||||
href: 'https://vuetifyjs.com/getting-started/frequently-asked-questions'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -46,34 +46,4 @@
|
|||||||
</v-form>
|
</v-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script src="./login.js"></script>
|
||||||
export default {
|
|
||||||
data: () => ({
|
|
||||||
valid: false,
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
usernameRules: [
|
|
||||||
v => !!v || 'Username is required'
|
|
||||||
],
|
|
||||||
passwordRules: [
|
|
||||||
v => !!v || 'Password is required'
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
methods: {
|
|
||||||
login () {
|
|
||||||
this.$http.post('/login/password', {
|
|
||||||
username: this.username,
|
|
||||||
password: this.password
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.$router.push('/')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.response)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
|
<h2 class="headline font-weight-bold mb-10">
|
||||||
|
Playback
|
||||||
|
</h2>
|
||||||
|
|
||||||
<v-row justify="center">
|
<v-row justify="center">
|
||||||
<v-btn
|
<v-btn
|
||||||
:disabled="playDisabled || !isTimerValid"
|
:disabled="playDisabled || !isTimerValid"
|
||||||
@@ -32,6 +36,109 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12">
|
||||||
|
<h2 class="headline font-weight-bold mb-5">
|
||||||
|
Profiles
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<v-row justify="center">
|
||||||
|
<v-select
|
||||||
|
v-model="selectedProfile"
|
||||||
|
:items="profileItems"
|
||||||
|
return-object
|
||||||
|
label="Profiles"
|
||||||
|
class="mx-3 mb-5"
|
||||||
|
@change="loadProfile"
|
||||||
|
/>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
class="mx-3"
|
||||||
|
:disabled="profileItems.length < 2"
|
||||||
|
@click="deleteProfile"
|
||||||
|
>
|
||||||
|
Delete Profile
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
class="mx-3"
|
||||||
|
@click="updateProfile"
|
||||||
|
>
|
||||||
|
Save Profile
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-snackbar
|
||||||
|
v-model="updateProfileSnackbar"
|
||||||
|
timeout="3000"
|
||||||
|
>
|
||||||
|
{{ updateProfileText }}
|
||||||
|
|
||||||
|
<template v-slot:action="{ attrs }">
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
v-bind="attrs"
|
||||||
|
@click="updateProfileSnackbar = false"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
|
||||||
|
<v-dialog
|
||||||
|
v-model="profileDialog"
|
||||||
|
max-width="600px"
|
||||||
|
>
|
||||||
|
<template v-slot:activator="{ on, attrs }">
|
||||||
|
<v-btn
|
||||||
|
v-bind="attrs"
|
||||||
|
class="mx-3"
|
||||||
|
v-on="on"
|
||||||
|
@click="profileName = ''"
|
||||||
|
>
|
||||||
|
Save Profile As...
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-form
|
||||||
|
v-model="isProfileValid"
|
||||||
|
>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>
|
||||||
|
<span class="text-h5">Profile Name</span>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-text-field
|
||||||
|
v-model="profileName"
|
||||||
|
label="Profile Name"
|
||||||
|
:rules="[rules.required()]"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer />
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
@click="profileDialog = false"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
:disabled="!isProfileValid"
|
||||||
|
@click="saveProfile"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-form>
|
||||||
|
</v-dialog>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<h2 class="headline font-weight-bold mb-5">
|
<h2 class="headline font-weight-bold mb-5">
|
||||||
Timer
|
Timer
|
||||||
@@ -273,7 +380,10 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12">
|
<v-col
|
||||||
|
v-if="canUpload"
|
||||||
|
cols="12"
|
||||||
|
>
|
||||||
<h2 class="headline font-weight-bold mb-5">
|
<h2 class="headline font-weight-bold mb-5">
|
||||||
Samples
|
Samples
|
||||||
</h2>
|
</h2>
|
||||||
@@ -290,6 +400,14 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
:disabled="playDisabled"
|
||||||
|
@click="removeSample(index)"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
<v-slider
|
<v-slider
|
||||||
v-model="sample.volume"
|
v-model="sample.volume"
|
||||||
label="Volume"
|
label="Volume"
|
||||||
@@ -434,83 +552,23 @@
|
|||||||
</v-dialog>
|
</v-dialog>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12">
|
<v-snackbar
|
||||||
<h2 class="headline font-weight-bold mb-5">
|
v-model="errorSnackbar"
|
||||||
Profiles
|
color="error"
|
||||||
</h2>
|
timeout="3000"
|
||||||
|
>
|
||||||
|
{{ errorSnackbarText }}
|
||||||
|
|
||||||
<v-row justify="center">
|
<template v-slot:action="{ attrs }">
|
||||||
<v-select
|
|
||||||
v-model="selectedProfile"
|
|
||||||
:items="profileItems"
|
|
||||||
return-object
|
|
||||||
label="Profiles"
|
|
||||||
class="mx-3 mb-5"
|
|
||||||
@change="loadProfile"
|
|
||||||
/>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
class="mx-3"
|
|
||||||
:disabled="profileItems.length < 2"
|
|
||||||
@click="deleteProfile"
|
|
||||||
>
|
|
||||||
Delete Profile
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-dialog
|
|
||||||
v-model="profileDialog"
|
|
||||||
max-width="600px"
|
|
||||||
>
|
|
||||||
<template v-slot:activator="{ on, attrs }">
|
|
||||||
<v-btn
|
|
||||||
v-bind="attrs"
|
|
||||||
class="mx-3"
|
|
||||||
v-on="on"
|
|
||||||
>
|
|
||||||
Save Profile
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
<v-form
|
|
||||||
v-model="isProfileValid"
|
|
||||||
>
|
|
||||||
<v-card>
|
|
||||||
<v-card-title>
|
|
||||||
<span class="text-h5">Profile Name</span>
|
|
||||||
</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<v-container>
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-text-field
|
|
||||||
v-model="profileName"
|
|
||||||
label="Profile Name"
|
|
||||||
:rules="[rules.required()]"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-container>
|
|
||||||
</v-card-text>
|
|
||||||
<v-card-actions>
|
|
||||||
<v-spacer />
|
|
||||||
<v-btn
|
<v-btn
|
||||||
text
|
text
|
||||||
@click="profileDialog = false"
|
v-bind="attrs"
|
||||||
|
@click="errorSnackbar = false"
|
||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
</template>
|
||||||
text
|
</v-snackbar>
|
||||||
:disabled="!isProfileValid"
|
|
||||||
@click="saveProfile"
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</v-btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-form>
|
|
||||||
</v-dialog>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -57,34 +57,4 @@
|
|||||||
</v-form>
|
</v-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script src="./register.js"></script>
|
||||||
export default {
|
|
||||||
data: () => ({
|
|
||||||
valid: false,
|
|
||||||
name: '',
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
rules: {
|
|
||||||
required: v => !!v || 'Required'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
methods: {
|
|
||||||
register () {
|
|
||||||
this.$http.post('/users', {
|
|
||||||
name: this.name,
|
|
||||||
username: this.username,
|
|
||||||
password: this.password,
|
|
||||||
isAdmin: 1
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.$router.push('/login')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.response)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
77
src/components/admin.js
Normal file
77
src/components/admin.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
export default {
|
||||||
|
name: 'Admin',
|
||||||
|
|
||||||
|
data: () => ({
|
||||||
|
currentUser: {},
|
||||||
|
users: [],
|
||||||
|
snackbar: false,
|
||||||
|
updateText: ''
|
||||||
|
}),
|
||||||
|
created () {
|
||||||
|
this.getCurrentUser()
|
||||||
|
this.getUsers()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getUsers () {
|
||||||
|
this.$http.get('/users')
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.users = response.data.users
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getCurrentUser () {
|
||||||
|
this.$http.get('/users/current')
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.currentUser = response.data.user
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateUserAdmin (id, isAdmin) {
|
||||||
|
this.$http.patch('/users/admin/'.concat(id), {
|
||||||
|
isAdmin: isAdmin
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.updateText = 'User updated'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.error(error.response)
|
||||||
|
this.updateText = 'Error updating user'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateUserUpload (id, canUpload) {
|
||||||
|
this.$http.patch('/users/upload/'.concat(id), {
|
||||||
|
canUpload: canUpload
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.updateText = 'User updated'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.error(error.response)
|
||||||
|
this.updateText = 'Error updating user'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteUser (id) {
|
||||||
|
this.$http.delete('/users/'.concat(id))
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.getUsers()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/components/appbar.js
Normal file
51
src/components/appbar.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
export default {
|
||||||
|
name: 'AppBar',
|
||||||
|
|
||||||
|
data: () => ({
|
||||||
|
drawyer: false,
|
||||||
|
isAdmin: false
|
||||||
|
}),
|
||||||
|
created () {
|
||||||
|
this.getCurrentUser()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
home () {
|
||||||
|
this.$router.push('/')
|
||||||
|
},
|
||||||
|
admin () {
|
||||||
|
this.$router.push('/admin')
|
||||||
|
},
|
||||||
|
logout () {
|
||||||
|
this.$http.get('/logout')
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.$router.push('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getCurrentUser () {
|
||||||
|
this.$http.get('/users/current')
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.isAdmin = response.data.user.isAdmin
|
||||||
|
this.$vuetify.theme.dark = response.data.user.darkMode
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
this.isAdmin = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toggleDarkMode () {
|
||||||
|
this.$http.patch('/users/dark-mode', {
|
||||||
|
darkMode: this.$vuetify.theme.dark
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/components/login.js
Normal file
29
src/components/login.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
export default {
|
||||||
|
data: () => ({
|
||||||
|
valid: false,
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
usernameRules: [
|
||||||
|
v => !!v || 'Username is required'
|
||||||
|
],
|
||||||
|
passwordRules: [
|
||||||
|
v => !!v || 'Password is required'
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
login () {
|
||||||
|
this.$http.post('/login/password', {
|
||||||
|
username: this.username,
|
||||||
|
password: this.password
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.$router.push('/')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ export default {
|
|||||||
profileDialog: false,
|
profileDialog: false,
|
||||||
profileName: '',
|
profileName: '',
|
||||||
isProfileValid: false,
|
isProfileValid: false,
|
||||||
|
updateProfileSnackbar: false,
|
||||||
|
updateProfileText: '',
|
||||||
playDisabled: false,
|
playDisabled: false,
|
||||||
isTimerEnabled: false,
|
isTimerEnabled: false,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
@@ -32,6 +34,7 @@ export default {
|
|||||||
isTremoloEnabled: false,
|
isTremoloEnabled: false,
|
||||||
tremoloFrequency: 0.5,
|
tremoloFrequency: 0.5,
|
||||||
tremoloDepth: 0.5,
|
tremoloDepth: 0.5,
|
||||||
|
isReverbEnabled: false,
|
||||||
allSamples: [],
|
allSamples: [],
|
||||||
loadedSamples: [],
|
loadedSamples: [],
|
||||||
selectedSample: null,
|
selectedSample: null,
|
||||||
@@ -39,8 +42,10 @@ export default {
|
|||||||
addSampleDialog: false,
|
addSampleDialog: false,
|
||||||
checkedSamples: [],
|
checkedSamples: [],
|
||||||
sampleName: '',
|
sampleName: '',
|
||||||
file: null,
|
|
||||||
isSampleUploadValid: false,
|
isSampleUploadValid: false,
|
||||||
|
canUpload: false,
|
||||||
|
errorSnackbar: false,
|
||||||
|
errorSnackbarText: '',
|
||||||
rules: {
|
rules: {
|
||||||
lt (n) {
|
lt (n) {
|
||||||
return value => (!isNaN(parseInt(value, 10)) && value < n) || 'Must be less than ' + n
|
return value => (!isNaN(parseInt(value, 10)) && value < n) || 'Must be less than ' + n
|
||||||
@@ -71,8 +76,9 @@ export default {
|
|||||||
this.tremolo = new Tremolo()
|
this.tremolo = new Tremolo()
|
||||||
this.lfo = new LFO()
|
this.lfo = new LFO()
|
||||||
this.players = new Players()
|
this.players = new Players()
|
||||||
this.populateProfileItems()
|
this.populateProfileItems(0)
|
||||||
this.getSamples()
|
this.getSamples()
|
||||||
|
this.getCurrentUser()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
play () {
|
play () {
|
||||||
@@ -108,12 +114,14 @@ export default {
|
|||||||
this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000)
|
this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000)
|
||||||
|
|
||||||
this.loadedSamples.forEach(s => {
|
this.loadedSamples.forEach(s => {
|
||||||
|
this.players.player(s.id).loop = true
|
||||||
this.players.player(s.id).unsync().sync().start(0).stop(this.duration)
|
this.players.player(s.id).unsync().sync().start(0).stop(this.duration)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.noise.sync().start(0)
|
this.noise.sync().start(0)
|
||||||
|
|
||||||
this.loadedSamples.forEach(s => {
|
this.loadedSamples.forEach(s => {
|
||||||
|
this.players.player(s.id).loop = true
|
||||||
this.players.player(s.id).unsync().sync().start(0)
|
this.players.player(s.id).unsync().sync().start(0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -181,7 +189,7 @@ export default {
|
|||||||
this.noise.connect(this.filter)
|
this.noise.connect(this.filter)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
populateProfileItems () {
|
populateProfileItems (profileId) {
|
||||||
this.$http.get('/profiles')
|
this.$http.get('/profiles')
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -189,7 +197,7 @@ export default {
|
|||||||
this.addDefaultProfile()
|
this.addDefaultProfile()
|
||||||
} else {
|
} else {
|
||||||
this.profileItems = response.data.profiles
|
this.profileItems = response.data.profiles
|
||||||
this.selectedProfile = this.profileItems[0]
|
this.selectedProfile = this.profileItems[profileId]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -201,7 +209,9 @@ export default {
|
|||||||
this.$http.post('/profiles/default')
|
this.$http.post('/profiles/default')
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.selectedProfile = { id: response.data.id, text: 'Default' }
|
const defaultProfile = { id: response.data.id, text: 'Default' }
|
||||||
|
this.profileItems = [defaultProfile]
|
||||||
|
this.selectedProfile = defaultProfile
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -227,26 +237,44 @@ export default {
|
|||||||
tremoloDepth: this.tremoloDepth,
|
tremoloDepth: this.tremoloDepth,
|
||||||
samples: this.loadedSamples
|
samples: this.loadedSamples
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
const id = response.data.id
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.profileDialog = false
|
this.profileDialog = false
|
||||||
this.populateProfileItems()
|
console.log('repsonse.data.id: ', response.data.id)
|
||||||
|
this.populateProfileItems(response.data.id - 1)
|
||||||
this.$http.get('/profiles')
|
}
|
||||||
.then(response => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateProfile () {
|
||||||
|
this.$http.put('/profiles/'.concat(this.selectedProfile.id), {
|
||||||
|
isTimerEnabled: this.isTimerEnabled,
|
||||||
|
duration: this.duration,
|
||||||
|
volume: this.volume,
|
||||||
|
noiseColor: this.noiseColor,
|
||||||
|
isFilterEnabled: this.isFilterEnabled,
|
||||||
|
filterType: this.filterType,
|
||||||
|
filterCutoff: this.filterCutoff,
|
||||||
|
isLFOFilterCutoffEnabled: this.isLFOFilterCutoffEnabled,
|
||||||
|
lfoFilterCutoffFrequency: this.lfoFilterCutoffFrequency,
|
||||||
|
lfoFilterCutoffLow: this.lfoFilterCutoffRange[0],
|
||||||
|
lfoFilterCutoffHigh: this.lfoFilterCutoffRange[1],
|
||||||
|
isTremoloEnabled: this.isTremoloEnabled,
|
||||||
|
tremoloFrequency: this.tremoloFrequency,
|
||||||
|
tremoloDepth: this.tremoloDepth,
|
||||||
|
samples: this.loadedSamples
|
||||||
|
}).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.profileItems = response.data.profiles
|
this.updateProfileText = 'Profile saved'
|
||||||
this.selectedProfile = { id: id, text: this.profileName }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.response)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error.response)
|
console.error(error.response)
|
||||||
|
this.updateProfileText = 'Error saving profile'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.updateProfileSnackbar = true
|
||||||
},
|
},
|
||||||
loadProfile () {
|
loadProfile () {
|
||||||
this.$http.get('/profiles/'.concat(this.selectedProfile.id))
|
this.$http.get('/profiles/'.concat(this.selectedProfile.id))
|
||||||
@@ -280,7 +308,7 @@ export default {
|
|||||||
this.$http.delete('/profiles/'.concat(this.selectedProfile.id))
|
this.$http.delete('/profiles/'.concat(this.selectedProfile.id))
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.populateProfileItems()
|
this.populateProfileItems(0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -294,7 +322,7 @@ export default {
|
|||||||
this.allSamples = response.data.samples
|
this.allSamples = response.data.samples
|
||||||
this.allSamples.forEach(s => {
|
this.allSamples.forEach(s => {
|
||||||
if (!this.players.has(s.id)) {
|
if (!this.players.has(s.id)) {
|
||||||
this.players.add(s.id, '/samples/' + s.name).toDestination()
|
this.players.add(s.id, '/samples/' + s.user + '_' + s.name).toDestination()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -320,6 +348,10 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
if (error.response.status === 409) {
|
||||||
|
this.errorSnackbarText = 'Upload Failed: Duplicate Sample Name'
|
||||||
|
this.errorSnackbar = true
|
||||||
|
}
|
||||||
console.error(error.response)
|
console.error(error.response)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -328,13 +360,29 @@ export default {
|
|||||||
addSample () {
|
addSample () {
|
||||||
this.checkedSamples.forEach(i => {
|
this.checkedSamples.forEach(i => {
|
||||||
const load = this.allSamples.find(e => e.id === i)
|
const load = this.allSamples.find(e => e.id === i)
|
||||||
|
load.volume = -10
|
||||||
this.loadedSamples.push(load)
|
this.loadedSamples.push(load)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.addSampleDialog = false
|
this.addSampleDialog = false
|
||||||
|
this.checkedSamples = []
|
||||||
},
|
},
|
||||||
updateSampleVolume (id, index) {
|
updateSampleVolume (id, index) {
|
||||||
this.players.player(id).volume.value = this.loadedSamples[index].volume
|
this.players.player(id).volume.value = this.loadedSamples[index].volume
|
||||||
|
},
|
||||||
|
removeSample (index) {
|
||||||
|
this.loadedSamples.splice(index, 1)
|
||||||
|
},
|
||||||
|
getCurrentUser () {
|
||||||
|
this.$http.get('/users/current')
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.canUpload = response.data.user.canUpload
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/components/register.js
Normal file
31
src/components/register.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
export default {
|
||||||
|
data: () => ({
|
||||||
|
valid: false,
|
||||||
|
name: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
rules: {
|
||||||
|
required: v => !!v || 'Required'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
register () {
|
||||||
|
this.$http.post('/users', {
|
||||||
|
name: this.name,
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
isAdmin: 1,
|
||||||
|
darkMode: 0,
|
||||||
|
canUpload: 1
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.$router.push('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error.response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
import Home from '../views/Home.vue'
|
import Home from '../views/HomeView.vue'
|
||||||
import instance from '../axios'
|
import instance from '../axios'
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
@@ -13,24 +13,24 @@ const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'Signin',
|
name: 'Login',
|
||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
// which is lazy-loaded when the route is visited.
|
// which is lazy-loaded when the route is visited.
|
||||||
component: () => import(/* webpackChunkName: "about" */ '../views/Signin.vue')
|
component: () => import(/* webpackChunkName: "about" */ '../views/LoginView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/register',
|
path: '/register',
|
||||||
name: 'Signup',
|
name: 'Register',
|
||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
// which is lazy-loaded when the route is visited.
|
// which is lazy-loaded when the route is visited.
|
||||||
component: () => import(/* webpackChunkName: "about" */ '../views/Signup.vue')
|
component: () => import(/* webpackChunkName: "about" */ '../views/RegisterView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
name: 'Admin',
|
name: 'Admin',
|
||||||
component: () => import(/* webpackChunkName: "about" */ '../views/AdminPage.vue')
|
component: () => import(/* webpackChunkName: "about" */ '../views/AdminView.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="about">
|
|
||||||
<h1>This is an about page</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import Admin from '../components/Admin'
|
import Admin from '../components/Admin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AdminPage',
|
name: 'AdminView',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
Admin
|
Admin
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import Noise from '../components/Noise'
|
import Noise from '../components/Noise'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Home',
|
name: 'HomeView',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
Noise
|
Noise
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import Login from '../components/Login'
|
import Login from '../components/Login'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Signin',
|
name: 'LoginView',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
Login
|
Login
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import Register from '../components/Register'
|
import Register from '../components/Register'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Signup',
|
name: 'RegisterView',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
Register
|
Register
|
||||||
Reference in New Issue
Block a user