mirror of
https://github.com/wassname/talk.git
synced 2026-07-20 12:40:47 +08:00
Merge
This commit is contained in:
+2
-1
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"verbose": true,
|
||||
"ignore": ["test/*", "client/*", "dist/*"]
|
||||
"ignore": ["test/*", "client/*", "dist/*"],
|
||||
"ext": "js,json,graphql"
|
||||
}
|
||||
|
||||
@@ -2,13 +2,21 @@ import {graphql} from 'react-apollo';
|
||||
import STREAM_QUERY from './streamQuery.graphql';
|
||||
import MY_COMMENT_HISTORY from './myCommentHistory.graphql';
|
||||
|
||||
import pym from 'coral-framework/PymConnection';
|
||||
let url = pym.parentUrl.split('#')[0] || 'http://localhost:3000/';
|
||||
function getQueryVariable(variable) {
|
||||
let query = window.location.search.substring(1);
|
||||
let vars = query.split('&');
|
||||
for (let i = 0; i < vars.length; i++) {
|
||||
let pair = vars[i].split('=');
|
||||
if (decodeURIComponent(pair[0]) === variable) {
|
||||
return decodeURIComponent(pair[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const queryStream = graphql(STREAM_QUERY, {
|
||||
options: () => ({
|
||||
variables: {
|
||||
asset_url: url
|
||||
asset_url: getQueryVariable('asset_url')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export default {
|
||||
email: email => (/^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(email)),
|
||||
email: email => (/^([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(email)),
|
||||
password: pass => (/^(?=.{8,}).*$/.test(pass)),
|
||||
confirmPassword: () => true,
|
||||
displayName: displayName => (/^[a-zA-Z0-9_]+$/.test(displayName))
|
||||
|
||||
@@ -120,7 +120,7 @@ class CommentBox extends Component {
|
||||
cStyle={!length || (charCount && length > charCount) ? 'lightGrey' : 'darkGrey'}
|
||||
className={`${name}-button`}
|
||||
onClick={this.postComment}>
|
||||
{lang.t('POST')}
|
||||
{lang.t('post')}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
+39
-25
@@ -7,31 +7,41 @@ const CommentModel = require('../../models/comment');
|
||||
const CommentsService = require('../../services/comments');
|
||||
|
||||
/**
|
||||
* Retrieves comments by an array of asset id's.
|
||||
* Retrieves comments by an array of asset id's, results are returned in reverse
|
||||
* chronological order.
|
||||
* @param {Array} ids array of ids to lookup
|
||||
*/
|
||||
const genCommentsByAssetID = (context, ids) => CommentModel.find({
|
||||
asset_id: {
|
||||
$in: ids
|
||||
},
|
||||
parent_id: null,
|
||||
status: {
|
||||
$in: [null, 'ACCEPTED']
|
||||
}
|
||||
}).then(util.arrayJoinBy(ids, 'asset_id'));
|
||||
const genCommentsByAssetID = (context, ids) => {
|
||||
return CommentModel.find({
|
||||
asset_id: {
|
||||
$in: ids
|
||||
},
|
||||
parent_id: null,
|
||||
status: {
|
||||
$in: [null, 'ACCEPTED']
|
||||
}
|
||||
})
|
||||
.sort({created_at: -1})
|
||||
.then(util.arrayJoinBy(ids, 'asset_id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves comments by an array of parent ids.
|
||||
* Retrieves comments by an array of parent ids, results are returned in
|
||||
* chronological order.
|
||||
* @param {Array} ids array of ids to lookup
|
||||
*/
|
||||
const genCommentsByParentID = (context, ids) => CommentModel.find({
|
||||
parent_id: {
|
||||
$in: ids
|
||||
},
|
||||
status: {
|
||||
$in: [null, 'ACCEPTED']
|
||||
}
|
||||
}).then(util.arrayJoinBy(ids, 'parent_id'));
|
||||
const genCommentsByParentID = (context, ids) => {
|
||||
return CommentModel.find({
|
||||
parent_id: {
|
||||
$in: ids
|
||||
},
|
||||
status: {
|
||||
$in: [null, 'ACCEPTED']
|
||||
}
|
||||
})
|
||||
.sort({created_at: 1})
|
||||
.then(util.arrayJoinBy(ids, 'parent_id'));
|
||||
};
|
||||
|
||||
const getCommentsByStatusAndAssetID = (context, {status = null, asset_id = null}) => {
|
||||
|
||||
@@ -52,7 +62,7 @@ const getCommentsByActionTypeAndAssetID = (context, {action_type, asset_id = nul
|
||||
id: {
|
||||
$in: actions.map((action) => action.item_id)
|
||||
}
|
||||
});
|
||||
}).sort({created_at: 1});
|
||||
|
||||
if (asset_id) {
|
||||
comments = comments.where({asset_id});
|
||||
@@ -62,11 +72,15 @@ const getCommentsByActionTypeAndAssetID = (context, {action_type, asset_id = nul
|
||||
});
|
||||
};
|
||||
|
||||
const genCommentsByAuthorID = (context, authorIDs) => CommentModel.find({
|
||||
author_id: {
|
||||
$in: authorIDs
|
||||
}
|
||||
}).then(util.arrayJoinBy(authorIDs, 'author_id'));
|
||||
const genCommentsByAuthorID = (context, authorIDs) => {
|
||||
return CommentModel.find({
|
||||
author_id: {
|
||||
$in: authorIDs
|
||||
}
|
||||
})
|
||||
.sort({created_at: -1})
|
||||
.then(util.arrayJoinBy(authorIDs, 'author_id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a set of loaders based on a GraphQL context.
|
||||
|
||||
@@ -37,7 +37,7 @@ module.exports = (context) => {
|
||||
// TODO: refactor to something that'll return an error in the event an attempt
|
||||
// is made to mutate state while not logged in. There's got to be a better way
|
||||
// to do this.
|
||||
if (context.user) {
|
||||
if (context.user && context.user.can('mutation:createAction', 'mutation:deleteAction')) {
|
||||
return {
|
||||
Action: {
|
||||
create: (action) => createAction(context, action),
|
||||
|
||||
@@ -144,7 +144,7 @@ module.exports = (context) => {
|
||||
// TODO: refactor to something that'll return an error in the event an attempt
|
||||
// is made to mutate state while not logged in. There's got to be a better way
|
||||
// to do this.
|
||||
if (context.user) {
|
||||
if (context.user && context.user.can('mutation:createComment')) {
|
||||
return {
|
||||
Comment: {
|
||||
create: (comment) => createPublicComment(context, comment)
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = (context) => {
|
||||
// TODO: refactor to something that'll return an error in the event an attempt
|
||||
// is made to mutate state while not logged in. There's got to be a better way
|
||||
// to do this.
|
||||
if (context.user) {
|
||||
if (context.user && context.user.can('mutation:updateUserSettings')) {
|
||||
return {
|
||||
User: {
|
||||
updateSettings: (settings) => updateUserSettings(context, settings)
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
interface ActionableItem {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type UserSettings {
|
||||
# bio of the user.
|
||||
bio: String
|
||||
}
|
||||
|
||||
input CommentsInput {
|
||||
# current status of a comment.
|
||||
status: COMMENT_STATUS
|
||||
|
||||
# asset that a comment is on.
|
||||
asset_id: ID
|
||||
|
||||
# action type to find comments that have an action with.
|
||||
action_type: ACTION_TYPE
|
||||
}
|
||||
|
||||
# Any person who can author comments, create actions, and view comments on a
|
||||
# stream.
|
||||
type User {
|
||||
id: ID!
|
||||
|
||||
# display name of a user.
|
||||
displayName: String!
|
||||
|
||||
# actions against a specific user.
|
||||
actions: [ActionSummary]
|
||||
|
||||
# settings for a user.
|
||||
settings: UserSettings
|
||||
|
||||
# returns all comments based on a query.
|
||||
comments(query: CommentsInput): [Comment]
|
||||
}
|
||||
|
||||
type Comment {
|
||||
id: ID!
|
||||
|
||||
# the actual comment data.
|
||||
body: String!
|
||||
|
||||
# the user who authored the comment.
|
||||
user: User
|
||||
|
||||
# the replies that were made to the comment.
|
||||
replies(limit: Int = 3): [Comment]
|
||||
|
||||
# the actions made against a comment.
|
||||
actions: [ActionSummary]
|
||||
|
||||
# the asset that a comment was made on.
|
||||
asset: Asset
|
||||
|
||||
# the current status of a comment.
|
||||
status: COMMENT_STATUS
|
||||
|
||||
# the time when the comment was created
|
||||
created_at: String!
|
||||
}
|
||||
|
||||
enum ITEM_TYPE {
|
||||
ASSETS
|
||||
COMMENTS
|
||||
USERS
|
||||
}
|
||||
|
||||
enum ACTION_TYPE {
|
||||
LIKE
|
||||
FLAG
|
||||
}
|
||||
|
||||
type Action {
|
||||
id: ID!
|
||||
action_type: ACTION_TYPE!
|
||||
|
||||
item_id: ID!
|
||||
item_type: ITEM_TYPE!
|
||||
item: ActionableItem
|
||||
|
||||
user: User!
|
||||
updated_at: String
|
||||
created_at: String
|
||||
}
|
||||
|
||||
type ActionSummary {
|
||||
action_type: ACTION_TYPE!
|
||||
item_type: ITEM_TYPE!
|
||||
count: Int
|
||||
current_user: Action
|
||||
}
|
||||
|
||||
enum MODERATION_MODE {
|
||||
PRE
|
||||
POST
|
||||
}
|
||||
|
||||
type Settings {
|
||||
moderation: MODERATION_MODE!
|
||||
infoBoxEnable: Boolean
|
||||
infoBoxContent: String
|
||||
closeTimeout: Int
|
||||
closedMessage: String
|
||||
charCountEnable: Boolean
|
||||
charCount: Int
|
||||
requireEmailConfirmation: Boolean
|
||||
}
|
||||
|
||||
type Asset {
|
||||
id: ID!
|
||||
title: String
|
||||
url: String
|
||||
comments: [Comment]
|
||||
settings: Settings!
|
||||
closedAt: String
|
||||
created_at: String
|
||||
}
|
||||
|
||||
enum COMMENT_STATUS {
|
||||
ACCEPTED
|
||||
REJECTED
|
||||
PREMOD
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
# retrieves site wide settings and defaults.
|
||||
settings: Settings
|
||||
|
||||
# retrieves all assets.
|
||||
assets: [Asset]
|
||||
|
||||
# retrieves a specific asset.
|
||||
asset(id: ID, url: String): Asset
|
||||
|
||||
# retrieves comments based on the input query.
|
||||
comments(query: CommentsInput): [Comment]
|
||||
|
||||
# retrieves the current logged in user.
|
||||
me: User
|
||||
}
|
||||
|
||||
input CreateActionInput {
|
||||
# the type of action.
|
||||
action_type: ACTION_TYPE!
|
||||
|
||||
# the type of the item.
|
||||
item_type: ITEM_TYPE!
|
||||
|
||||
# the id of the item that is related to the action.
|
||||
item_id: ID!
|
||||
}
|
||||
|
||||
input UpdateUserSettingsInput {
|
||||
# user bio
|
||||
bio: String!
|
||||
}
|
||||
|
||||
type RootMutation {
|
||||
# creates a comment on the asset.
|
||||
createComment(asset_id: ID!, parent_id: ID, body: String!): Comment
|
||||
|
||||
# creates an action based on an input.
|
||||
createAction(action: CreateActionInput!): Action
|
||||
|
||||
# delete an action based on the action id.
|
||||
deleteAction(id: ID!): Boolean
|
||||
|
||||
# updates a user's settings, it will return if the query was successful.
|
||||
updateUserSettings(settings: UpdateUserSettingsInput!): Boolean
|
||||
}
|
||||
|
||||
schema {
|
||||
query: RootQuery
|
||||
mutation: RootMutation
|
||||
}
|
||||
+4
-173
@@ -2,179 +2,10 @@
|
||||
// `RootQuery.asset(id: ID, url: String!)` because we'll always need the url, if
|
||||
// this change is done now everything will likely break on the front end.
|
||||
|
||||
const typeDefs = [`
|
||||
interface ActionableItem {
|
||||
id: ID!
|
||||
}
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
type UserSettings {
|
||||
# bio of the user.
|
||||
bio: String
|
||||
}
|
||||
|
||||
input CommentsInput {
|
||||
# current status of a comment.
|
||||
status: COMMENT_STATUS
|
||||
|
||||
# asset that a comment is on.
|
||||
asset_id: ID
|
||||
|
||||
# action type to find comments that have an action with.
|
||||
action_type: ACTION_TYPE
|
||||
}
|
||||
|
||||
# Any person who can author comments, create actions, and view comments on a
|
||||
# stream.
|
||||
type User {
|
||||
id: ID!
|
||||
|
||||
# display name of a user.
|
||||
displayName: String!
|
||||
|
||||
# actions against a specific user.
|
||||
actions: [ActionSummary]
|
||||
|
||||
# settings for a user.
|
||||
settings: UserSettings
|
||||
|
||||
# returns all comments based on a query.
|
||||
comments(query: CommentsInput): [Comment]
|
||||
}
|
||||
|
||||
type Comment {
|
||||
id: ID!
|
||||
|
||||
# the actual comment data.
|
||||
body: String!
|
||||
|
||||
# the user who authored the comment.
|
||||
user: User
|
||||
|
||||
# the replies that were made to the comment.
|
||||
replies(limit: Int = 3): [Comment]
|
||||
|
||||
# the actions made against a comment.
|
||||
actions: [ActionSummary]
|
||||
|
||||
# the asset that a comment was made on.
|
||||
asset: Asset
|
||||
|
||||
# the current status of a comment.
|
||||
status: COMMENT_STATUS
|
||||
|
||||
# the time when the comment was created
|
||||
created_at: String!
|
||||
}
|
||||
|
||||
enum ITEM_TYPE {
|
||||
ASSETS
|
||||
COMMENTS
|
||||
USERS
|
||||
}
|
||||
|
||||
enum ACTION_TYPE {
|
||||
LIKE
|
||||
FLAG
|
||||
}
|
||||
|
||||
type Action {
|
||||
id: ID!
|
||||
action_type: ACTION_TYPE!
|
||||
|
||||
item_id: ID!
|
||||
item_type: ITEM_TYPE!
|
||||
item: ActionableItem
|
||||
|
||||
user: User!
|
||||
updated_at: String
|
||||
created_at: String
|
||||
}
|
||||
|
||||
type ActionSummary {
|
||||
action_type: ACTION_TYPE!
|
||||
item_type: ITEM_TYPE!
|
||||
count: Int
|
||||
current_user: Action
|
||||
}
|
||||
|
||||
type Settings {
|
||||
moderation: String
|
||||
infoBoxEnable: Boolean
|
||||
infoBoxContent: String
|
||||
closeTimeout: Int
|
||||
closedMessage: String
|
||||
charCountEnable: Boolean
|
||||
charCount: Int
|
||||
requireEmailConfirmation: Boolean
|
||||
}
|
||||
|
||||
type Asset {
|
||||
id: ID!
|
||||
title: String
|
||||
url: String
|
||||
comments: [Comment]
|
||||
settings: Settings!
|
||||
closedAt: String
|
||||
created_at: String
|
||||
}
|
||||
|
||||
enum COMMENT_STATUS {
|
||||
ACCEPTED
|
||||
REJECTED
|
||||
PREMOD
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
# retrieves site wide settings and defaults.
|
||||
settings: Settings
|
||||
|
||||
# retrieves all assets.
|
||||
assets: [Asset]
|
||||
|
||||
# retrieves a specific asset.
|
||||
asset(id: ID, url: String): Asset
|
||||
|
||||
# retrieves comments based on the input query.
|
||||
comments(query: CommentsInput): [Comment]
|
||||
|
||||
# retrieves the current logged in user.
|
||||
me: User
|
||||
}
|
||||
|
||||
input CreateActionInput {
|
||||
# the type of action.
|
||||
action_type: ACTION_TYPE!
|
||||
|
||||
# the type of the item.
|
||||
item_type: ITEM_TYPE!
|
||||
|
||||
# the id of the item that is related to the action.
|
||||
item_id: ID!
|
||||
}
|
||||
|
||||
input UpdateUserSettingsInput {
|
||||
# user bio
|
||||
bio: String!
|
||||
}
|
||||
|
||||
type RootMutation {
|
||||
# creates a comment on the asset.
|
||||
createComment(asset_id: ID!, parent_id: ID, body: String!): Comment
|
||||
|
||||
# creates an action based on an input.
|
||||
createAction(action: CreateActionInput!): Action
|
||||
|
||||
# delete an action based on the action id.
|
||||
deleteAction(id: ID!): Boolean
|
||||
|
||||
# updates a user's settings, it will return if the query was successful.
|
||||
updateUserSettings(settings: UpdateUserSettingsInput!): Boolean
|
||||
}
|
||||
|
||||
schema {
|
||||
query: RootQuery
|
||||
mutation: RootMutation
|
||||
}
|
||||
`];
|
||||
// Load the typeDefs from the graphql file.
|
||||
const typeDefs = fs.readFileSync(path.join(__dirname, 'typeDefs.graphql'), 'utf8');
|
||||
|
||||
module.exports = typeDefs;
|
||||
|
||||
@@ -130,6 +130,33 @@ UserSchema.method('hasRoles', function(...roles) {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* All the graph operations that are available for a user.
|
||||
* @type {Array}
|
||||
*/
|
||||
const USER_GRAPH_OPERATIONS = [
|
||||
'mutation:createComment',
|
||||
'mutation:createAction',
|
||||
'mutation:deleteAction',
|
||||
'mutation:updateUserSettings'
|
||||
];
|
||||
|
||||
/**
|
||||
* Can returns true if the user is allowed to perform a specific graph
|
||||
* operation.
|
||||
*/
|
||||
UserSchema.method('can', function(...actions) {
|
||||
if (actions.some((action) => USER_GRAPH_OPERATIONS.indexOf(action) === -1)) {
|
||||
throw new Error(`invalid actions: ${actions}`);
|
||||
}
|
||||
|
||||
if (this.status === 'BANNED') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Create the User model.
|
||||
const UserModel = mongoose.model('User', UserSchema);
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
const Assets = require('../../services/assets');
|
||||
|
||||
const body = 'Lorem ipsum dolor sponge amet, consectetur adipiscing clam. Ut lobortis sollicitudin pillar a ornare. Curabitur dignissim vestibulum cay non rhoncus. Cras laoreet ante vel nunc hendrerit, shelf imperdiet neque egestas. Suspendisse aliquet iaculis fermentum. Talk volutpat, tellus posuere laoreet consequat, mi lacus laoreet massa, sed vehicula mauris velit non lectus. Integer non trust nec neque congue faucibus porttitor sit amet elkhorn.';
|
||||
|
||||
router.get('/id/:asset_id', (req, res, next) => {
|
||||
|
||||
return Assets.findById(req.params.asset_id)
|
||||
.then(asset => {
|
||||
if (asset === null) {
|
||||
return res.json({'message': 'Asset not found'});
|
||||
}
|
||||
res.render('article', {
|
||||
title: asset.title,
|
||||
asset_url: asset.url,
|
||||
body: '',
|
||||
basePath: '/client/embed/stream'
|
||||
});
|
||||
})
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
|
||||
router.get('/title/:asset_title', (req, res) => {
|
||||
return res.render('article', {
|
||||
title: req.params.asset_title.split('-').join(' '),
|
||||
asset_url: '',
|
||||
body: body,
|
||||
basePath: '/client/embed/stream'
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/', (req, res, next) => {
|
||||
let skip = req.query.skip ? parseInt(req.query.skip) : 0;
|
||||
let limit = req.query.limit ? parseInt(req.query.limit) : 25;
|
||||
|
||||
return Assets.all(skip, limit)
|
||||
.then(assets => {
|
||||
res.render('articles', {
|
||||
assets: assets
|
||||
});
|
||||
})
|
||||
.catch(err => next(err));
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
+3
-7
@@ -4,17 +4,13 @@ const router = express.Router();
|
||||
router.use('/api/v1', require('./api'));
|
||||
router.use('/admin', require('./admin'));
|
||||
router.use('/embed', require('./embed'));
|
||||
router.use('/assets', require('./assets'));
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
return res.render('article', {
|
||||
title: 'Coral Talk',
|
||||
basePath: '/client/embed/stream'
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/assets/:asset_title', (req, res) => {
|
||||
return res.render('article', {
|
||||
title: req.params.asset_title.split('-').join(' '),
|
||||
asset_url: '',
|
||||
body: '',
|
||||
basePath: '/client/embed/stream'
|
||||
});
|
||||
});
|
||||
|
||||
+15
-9
@@ -88,15 +88,18 @@ module.exports = class AssetsService {
|
||||
* @param {String} value string to search by.
|
||||
* @return {Promise}
|
||||
*/
|
||||
static search(value) {
|
||||
static search(value = '', skip = null, limit = null) {
|
||||
if (value.length === 0) {
|
||||
return AssetsService.all();
|
||||
return AssetsService.all(skip, limit);
|
||||
} else {
|
||||
return AssetModel.find({
|
||||
$text: {
|
||||
$search: value
|
||||
}
|
||||
});
|
||||
return AssetModel
|
||||
.find({
|
||||
$text: {
|
||||
$search: value
|
||||
}
|
||||
})
|
||||
.skip(skip)
|
||||
.limit(limit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +113,10 @@ module.exports = class AssetsService {
|
||||
return AssetModel.find(query);
|
||||
}
|
||||
|
||||
static all() {
|
||||
return AssetModel.find({});
|
||||
static all(skip = null, limit = null) {
|
||||
return AssetModel
|
||||
.find({})
|
||||
.skip(skip)
|
||||
.limit(limit);
|
||||
}
|
||||
};
|
||||
|
||||
+22
-12
@@ -20,29 +20,39 @@
|
||||
<body>
|
||||
<main>
|
||||
<h1><%= title %></h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sponge amet, consectetur adipiscing clam.
|
||||
Ut lobortis sollicitudin pillar a ornare. Curabitur dignissim
|
||||
vestibulum cay non rhoncus. Cras laoreet ante vel nunc hendrerit,
|
||||
shelf imperdiet neque egestas. Suspendisse aliquet iaculis fermentum.
|
||||
Talk volutpat, tellus posuere laoreet consequat, mi lacus laoreet massa,
|
||||
sed vehicula mauris velit non lectus. Integer non trust nec neque congue
|
||||
faucibus porttitor sit amet elkhorn.
|
||||
</p>
|
||||
<p><a href="/admin">Visit the moderation console</a></p>
|
||||
<p><%= body %></p>
|
||||
<p><a href="/admin">Admin</a> - <a href="/assets">All Assets</a></p>
|
||||
<div id='coralStreamEmbed'></div>
|
||||
</main>
|
||||
|
||||
<script type='text/javascript' src='<%= basePath %>/pym.v1.min.js'></script>
|
||||
<script>
|
||||
var ready = false;
|
||||
var pymParent = new pym.Parent('coralStreamEmbed', '/embed/stream', {title: 'Talk Comments', id:'coralStreamIframe', name: 'coralStreamIframe'});
|
||||
|
||||
// default to using the window.location
|
||||
var url = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||
|
||||
// if a url is passed into the template prefer it to the current url
|
||||
<%if (asset_url.length > 0) { %>
|
||||
url = '<%= asset_url %>';
|
||||
<%}%>
|
||||
|
||||
var pymParent = new pym.Parent('coralStreamEmbed', '/embed/stream?asset_url=' + encodeURIComponent(url), {title: 'Talk Comments', id:'coralStreamIframe', name: 'coralStreamIframe', asset_url: url});
|
||||
pymParent.onMessage('height', function(height) {document.querySelector('#coralStreamEmbed iframe').height = height + 'px'})
|
||||
pymParent.onMessage('childReady', function () {
|
||||
var interval = setInterval(function () {
|
||||
if (ready) {
|
||||
window.clearInterval(interval);
|
||||
pymParent.sendMessage('DOMContentLoaded', window.location.hash);
|
||||
|
||||
// default to using the window.location
|
||||
var url = window.location.hash;
|
||||
|
||||
// if a url is passed into the template prefer it to the current url
|
||||
<%if (asset_url.length > 0) { %>
|
||||
url = '<%= asset_url %>';
|
||||
<%}%>
|
||||
|
||||
pymParent.sendMessage('DOMContentLoaded', url);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>
|
||||
Asset list
|
||||
</h1>
|
||||
<% assets.forEach(function (asset) { %>
|
||||
<a href="/assets/id/<%= asset.id %>"><%= asset.url %></a><br />
|
||||
<% }) %>
|
||||
<p>
|
||||
(For dev use only. FYI, you can: ?skip=100&limit=25)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user