@ -1,91 +0,0 @@
|
||||
// admin/domain.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const { /*SiteError,*/ SiteController } = require('../../../lib/site-lib');
|
||||
|
||||
class DomainController extends SiteController {
|
||||
|
||||
constructor (dtp) {
|
||||
super(dtp, 'admin:domain');
|
||||
}
|
||||
|
||||
async start ( ) {
|
||||
const router = express.Router();
|
||||
router.use(async (req, res, next) => {
|
||||
res.locals.currentView = 'admin';
|
||||
res.locals.adminView = 'domain';
|
||||
return next();
|
||||
});
|
||||
|
||||
router.param('domainId', this.populateDomainId.bind(this));
|
||||
|
||||
router.post('/:domainId', this.postUpdateDomain.bind(this));
|
||||
router.post('/', this.postCreateDomain.bind(this));
|
||||
|
||||
router.get('/create', this.getCreateForm.bind(this));
|
||||
router.get('/:domainId', this.getDomainView.bind(this));
|
||||
|
||||
router.get('/', this.getHomeView.bind(this));
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
async populateDomainId (req, res, next, domainId) {
|
||||
const { domain: domainService } = this.dtp.services;
|
||||
try {
|
||||
res.locals.domain = await domainService.getById(domainId);
|
||||
return next();
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async postUpdateDomain (req, res, next) {
|
||||
const { domain: domainService } = this.dtp.services;
|
||||
try {
|
||||
await domainService.update(res.locals.domain, req.body);
|
||||
res.redirect('/admin/domain');
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async postCreateDomain (req, res, next) {
|
||||
const { domain: domainService } = this.dtp.services;
|
||||
try {
|
||||
res.locals.domain = await domainService.create(req.body);
|
||||
res.redirect(`/admin/domain/${res.locals.domain._id}`);
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getDomainView (req, res) {
|
||||
res.render('admin/domain/form');
|
||||
}
|
||||
|
||||
async getCreateForm (req, res) {
|
||||
res.render('admin/domain/form');
|
||||
}
|
||||
|
||||
async getHomeView (req, res, next) {
|
||||
const { domain: domainService } = this.dtp.services;
|
||||
try {
|
||||
res.locals.pagination = this.getPaginationParameters(req, 10);
|
||||
res.locals.domains = await domainService.getDomains(res.locals.pagination);
|
||||
res.render('admin/domain/index');
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async (dtp) => {
|
||||
let controller = new DomainController(dtp);
|
||||
return controller;
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
// domain.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const DomainSchema = new Schema({
|
||||
created: { type: Date, default: Date.now, required: true, index: -1 },
|
||||
name: { type: String, required: true, lowercase: true, index: 1 },
|
||||
stats: {
|
||||
channelCount: { type: Number, default: 0, required: true },
|
||||
streamCount: { type: Number, default: 0, required: true },
|
||||
viewerCount: { type: Number, default: 0, required: true },
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Domain', DomainSchema);
|
@ -1,72 +0,0 @@
|
||||
// domain.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const striptags = require('striptags');
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const Domain = mongoose.model('Domain');
|
||||
|
||||
const { SiteService, SiteError } = require('../../lib/site-lib');
|
||||
|
||||
class DomainService extends SiteService {
|
||||
|
||||
constructor (dtp) {
|
||||
super(dtp, module.exports);
|
||||
}
|
||||
|
||||
async create (domainDefinition) {
|
||||
const NOW = new Date();
|
||||
const domain = new Domain();
|
||||
domain.created = NOW;
|
||||
domain.name = striptags(domainDefinition.name.trim().toLowerCase());
|
||||
await domain.save();
|
||||
return domain.toObject();
|
||||
}
|
||||
|
||||
async update (domain, domainDefinition) {
|
||||
await Domain.updateOne(
|
||||
{ _id: domain._id },
|
||||
{
|
||||
$set: {
|
||||
name: striptags(domainDefinition.name.trim().toLowerCase()),
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async getSiteDomain ( ) {
|
||||
return this.getByName(process.env.DTP_SITE_DOMAIN_KEY);
|
||||
}
|
||||
|
||||
async getById (domainId) {
|
||||
const domain = await Domain.findById(domainId).lean();
|
||||
return domain;
|
||||
}
|
||||
|
||||
async getByName (domainName) {
|
||||
const domain = await Domain.findOne({ name: domainName.toLowerCase().trim() }).lean();
|
||||
if (!domain) {
|
||||
throw new SiteError(404, 'Domain does not exist');
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
async getDomains (pagination) {
|
||||
const domains = await Domain
|
||||
.find()
|
||||
.sort({ name: 1 })
|
||||
.skip(pagination.skip)
|
||||
.limit(pagination.cpp)
|
||||
.lean();
|
||||
return domains;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
slug: 'domain',
|
||||
name: 'domain',
|
||||
create: (dtp) => { return new DomainService(dtp); },
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
extends ../layouts/main
|
||||
block content
|
||||
|
||||
table.uk-table
|
||||
thead
|
||||
th Channel Name
|
||||
th Domain
|
||||
th Created
|
||||
th Member
|
||||
th Audience
|
||||
th Status
|
||||
tbody
|
||||
each application in applications
|
||||
tr
|
||||
td
|
||||
a(href=`/admin/channel-application/${application._id}`)= application.name
|
||||
td= application.domain ? application.domain.name : 'N/A'
|
||||
td= moment(application.created).fromNow()
|
||||
td
|
||||
a(href=`/admin/member/${application.owner._id}`)= application.owner.username
|
||||
td= numeral(application.interview.audienceSize).format('0,0')
|
||||
td(class={
|
||||
'uk-text-primary': ['new','review'].includes(application.status),
|
||||
'uk-text-success': (application.status === 'approved'),
|
||||
'uk-text-danger': (application.status === 'rejected'),
|
||||
})= application.status
|
@ -1,79 +0,0 @@
|
||||
extends ../layouts/main
|
||||
block content
|
||||
|
||||
.uk-card.uk-card-secondary.uk-card-body.uk-margin
|
||||
fieldset.uk-fieldset
|
||||
legend.sr-only Channel Information
|
||||
div(uk-grid)
|
||||
.uk-width-expand
|
||||
.uk-margin
|
||||
label.uk-form-label Channel Name:
|
||||
.uk-text-large.uk-text-bold= application.name
|
||||
.uk-width-auto
|
||||
.uk-margin
|
||||
label.uk-form-label Owner:
|
||||
div
|
||||
a(href=`mailto:${application.owner.email}?subject=${encodeURIComponent(site.name)}${encodeURIComponent(': ')}${encodeURIComponent(application.name)}`)= application.owner.displayName || application.owner.email
|
||||
.uk-width-auto
|
||||
.uk-margin
|
||||
label.uk-form-label Phone:
|
||||
div
|
||||
a(href=`tel:${application.contact.phone.number}`)= application.contact.phone.number
|
||||
.uk-width-auto
|
||||
.uk-margin
|
||||
label.uk-form-label Submitted:
|
||||
div= moment(application.created).fromNow()
|
||||
|
||||
.uk-margin
|
||||
label.uk-form-label Description
|
||||
div!= marked(application.description)
|
||||
|
||||
div(uk-grid)
|
||||
.uk-width-auto
|
||||
.uk-margin
|
||||
label.uk-form-label Category
|
||||
div= application.category.name
|
||||
.uk-width-auto
|
||||
.uk-margin
|
||||
label.uk-form-label Short Name
|
||||
div= application.slug
|
||||
.uk-width-auto
|
||||
.uk-margin
|
||||
label.uk-form-label Search Tags
|
||||
div= application.tags ? application.tags.join(',') : 'N/A'
|
||||
|
||||
.uk-card.uk-card-secondary.uk-card-body.uk-margin
|
||||
fieldset.uk-fieldset
|
||||
legend.uk-legend Interview
|
||||
|
||||
div(uk-grid)
|
||||
div(class="uk-width-1-1 uk-width-auto@m")
|
||||
.uk-margin
|
||||
label.uk-form-label Audience Size
|
||||
div= application.interview.audienceSize
|
||||
div(class="uk-width-1-1 uk-width-auto@m")
|
||||
.uk-margin
|
||||
label.uk-form-label Demo URL
|
||||
div
|
||||
a(href= application.interview.demoUrl)= application.interview.demoUrl
|
||||
|
||||
.uk-margin
|
||||
label.uk-form-label History
|
||||
div!= marked(application.interview.history)
|
||||
|
||||
.uk-card.uk-card-secondary.uk-card-body.uk-margin
|
||||
form(method="POST", action=`/admin/channel-application/${application._id}`).uk-form
|
||||
.uk-margin
|
||||
label(for="rejected-reason").uk-form-label Rejection explanation
|
||||
textarea(id="rejected-reason", name="rejectedReason", rows="4", placeholder= "Enter reason for rejecting").uk-textarea
|
||||
div(uk-grid)
|
||||
.uk-width-auto
|
||||
button(type="submit", name="action", value="approve").uk-button.uk-button-primary
|
||||
span
|
||||
i.fas.fa-check
|
||||
span.uk-text-bold.uk-margin-small-left Approve
|
||||
.uk-width-auto
|
||||
button(type="submit", name="action", value="reject").uk-button.uk-button-danger
|
||||
span
|
||||
i.fas.fa-times
|
||||
span.uk-text-bold.uk-margin-small-left Reject
|
@ -1,28 +0,0 @@
|
||||
extends ../layouts/main
|
||||
block content
|
||||
|
||||
.uk-overflow-auto
|
||||
table.uk-table.uk-table-small.uk-table-divider
|
||||
thead
|
||||
th Channel
|
||||
th Owner
|
||||
th Category
|
||||
th Status
|
||||
th Created
|
||||
tbody
|
||||
each channel in channels
|
||||
tr
|
||||
td
|
||||
a(href=`/admin/channel/${channel._id}`)= channel.name
|
||||
|
||||
td
|
||||
a(href=`/admin/user/${channel.owner._id}`)= channel.owner.username
|
||||
|
||||
td= channel.category.name
|
||||
|
||||
td(class={
|
||||
'uk-text-success': (channel.status === 'live'),
|
||||
'uk-text-default': (channel.status === 'offline'),
|
||||
})= channel.status
|
||||
|
||||
td= moment(channel.created).format('MMM DD, YYYY')
|
@ -1,13 +0,0 @@
|
||||
extends ../layouts/main
|
||||
block content
|
||||
|
||||
- var formAction = domain ? `/admin/domain/${domain._id}` : "/admin/domain";
|
||||
|
||||
h2 Domain Manager
|
||||
|
||||
form(method="POST", action= formAction).uk-form
|
||||
.uk-margin
|
||||
label(for="name").uk-form-label Name
|
||||
input(id="name", name="name", type="text", placeholder= "Enter domain name", value= domain ? domain.name : undefined).uk-input
|
||||
.uk-margin
|
||||
button(type="submit").uk-button.uk-button-primary= domain ? 'Update domain' : 'Create domain'
|
@ -1,18 +0,0 @@
|
||||
extends ../layouts/main
|
||||
block content
|
||||
|
||||
.uk-margin
|
||||
div(uk-grid).uk-flex-middle
|
||||
.uk-width-expand
|
||||
h2 Domain Manager
|
||||
.uk-width-auto
|
||||
a(href="/admin/domain/create").uk-button.uk-button-primary
|
||||
span
|
||||
i.fas.fa-plus
|
||||
span.uk-margin-small-left Add domain
|
||||
|
||||
.uk-margin
|
||||
uk.uk-list
|
||||
each domain in domains
|
||||
li
|
||||
a(href=`/admin/domain/${domain._id}`)= domain.name
|
@ -1,19 +1,19 @@
|
||||
link(rel="apple-touch-icon" sizes="57x57" href=`/img/icon/${site.domainKey}/icon-57x57.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="60x60" href=`/img/icon/${site.domainKey}/icon-60x60.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="72x72" href=`/img/icon/${site.domainKey}/icon-72x72.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="76x76" href=`/img/icon/${site.domainKey}/icon-76x76.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="114x114" href=`/img/icon/${site.domainKey}/icon-114x114.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="120x120" href=`/img/icon/${site.domainKey}/icon-120x120.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="144x144" href=`/img/icon/${site.domainKey}/icon-144x144.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="152x152" href=`/img/icon/${site.domainKey}/icon-152x152.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="180x180" href=`/img/icon/${site.domainKey}/icon-180x180.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="32x32" href=`/img/icon/${site.domainKey}/icon-32x32.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="96x96" href=`/img/icon/${site.domainKey}/icon-96x96.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="16x16" href=`/img/icon/${site.domainKey}/icon-16x16.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="512x512" href=`/img/icon/${site.domainKey}/icon-512x512.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="384x384" href=`/img/icon/${site.domainKey}/icon-384x384.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="256x256" href=`/img/icon/${site.domainKey}/icon-512x512.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="192x192" href=`/img/icon/${site.domainKey}/icon-192x192.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="57x57" href=`/img/icon/icon-57x57.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="60x60" href=`/img/icon/icon-60x60.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="72x72" href=`/img/icon/icon-72x72.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="76x76" href=`/img/icon/icon-76x76.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="114x114" href=`/img/icon/icon-114x114.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="120x120" href=`/img/icon/icon-120x120.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="144x144" href=`/img/icon/icon-144x144.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="152x152" href=`/img/icon/icon-152x152.png?v=${pkg.version}`)
|
||||
link(rel="apple-touch-icon" sizes="180x180" href=`/img/icon/icon-180x180.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="32x32" href=`/img/icon/icon-32x32.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="96x96" href=`/img/icon/icon-96x96.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="16x16" href=`/img/icon/icon-16x16.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="512x512" href=`/img/icon/icon-512x512.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="384x384" href=`/img/icon/icon-384x384.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="256x256" href=`/img/icon/icon-512x512.png?v=${pkg.version}`)
|
||||
link(rel="icon" type="image/png" sizes="192x192" href=`/img/icon/icon-192x192.png?v=${pkg.version}`)
|
||||
link(rel="manifest" href=`/manifest.json?v=${pkg.version}`)
|
||||
meta(name="msapplication-TileColor" content="#f1c52f")
|
||||
meta(name="msapplication-TileImage" content=`/img/icon/ms-icon-144x144.png?v=${pkg.version}`)
|
||||
|
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 232 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 795 B |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 205 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 326 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 581 B After Width: | Height: | Size: 581 B |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 685 B |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 1.9 KiB |