Skip to content
This repository has been archived by the owner on Mar 18, 2021. It is now read-only.

Commit

Permalink
Merge pull request #23 from guardian/sw-show-campaign-assets
Browse files Browse the repository at this point in the history
Sw show campaign assets
  • Loading branch information
steppenwells committed Oct 11, 2016
2 parents bdd4142 + f6e49dc commit 081370a
Show file tree
Hide file tree
Showing 27 changed files with 503 additions and 29 deletions.
9 changes: 8 additions & 1 deletion app/controllers/App.scala
Expand Up @@ -20,7 +20,14 @@ class App(override val wsClient: WSClient) extends Controller with PandaAuthActi
case None => routes.Assets.versioned(jsFileName).toString
}

val clientConf = Map("tagManagerUrl" -> Config().tagManagerApiUrl)
val clientConf = Map(
"tagManagerUrl" -> Config().tagManagerApiUrl,
"composerUrl" -> Config().composerUrl,
"liveUrl" -> Config().liveUrl,
"previewUrl" -> Config().previewUrl,
"mediaAtomMakerUrl" -> Config().mediaAtomMakerUrl,
"ctaAtomMakerUrl" -> Config().ctaAtomMakerUrl
)

Ok(views.html.Application.app("Campaign Central", jsLocation, Json.toJson(clientConf).toString()))
}
Expand Down
6 changes: 5 additions & 1 deletion app/controllers/CampaignApi.scala
Expand Up @@ -11,7 +11,7 @@ import play.api.mvc.{Action, Controller}
import com.gu.pandomainauth.model.{User => PandaUser}
import model.command.ImportCampaignFromCAPICommand
import model.command.CommandError._
import repositories.{CampaignNotesRepository, CampaignRepository, ClientRepository, GoogleAnalytics}
import repositories._

class CampaignApi(override val wsClient: WSClient) extends Controller with PandaAuthActions {

Expand All @@ -37,6 +37,10 @@ class CampaignApi(override val wsClient: WSClient) extends Controller with Panda
GoogleAnalytics.getAnalyticsForCampaign(id).flatten map { c => Ok(Json.toJson(c)) } getOrElse NotFound
}

def getCampaignContent(id: String) = APIAuthAction { req =>
Ok(Json.toJson(CampaignContentRepository.getContentForCampaign(id)))
}

def getCampaignNotes(id: String) = APIAuthAction { req =>
Ok(Json.toJson(CampaignNotesRepository.getNotesForCampaign(id)))
}
Expand Down
26 changes: 23 additions & 3 deletions app/services/Config.scala
Expand Up @@ -36,6 +36,11 @@ sealed trait Config {
def clientTableName = s"campaign-central-$stage-clients"

def tagManagerApiUrl: String
def composerUrl: String
def liveUrl: String
def previewUrl: String
def mediaAtomMakerUrl: String
def ctaAtomMakerUrl: String


// remote configuration is used for things we don't want to check in to version control
Expand Down Expand Up @@ -96,7 +101,12 @@ class DevConfig extends Config {
override def pandaDomain: String = "local.dev-gutools.co.uk"
override def pandaAuthCallback: String = "https://campaign-central.local.dev-gutools.co.uk/oauthCallback"

override def tagManagerApiUrl = "https://tagmanager.local.dev-gutools.co.uk/hyper"
override def tagManagerApiUrl = "https://tagmanager.local.dev-gutools.co.uk"
override def composerUrl = "https://composer.local.dev-gutools.co.uk"
override def liveUrl = "https://www.theguardian.com"
override def previewUrl = "https://viewer.gutools.co.uk/preview"
override def mediaAtomMakerUrl = "https://media-atom-maker.local.dev-gutools.co.uk"
override def ctaAtomMakerUrl = "https://cta-atom-maker.local.dev-gutools.co.uk"
}

class CodeConfig extends Config {
Expand All @@ -107,7 +117,12 @@ class CodeConfig extends Config {
override def pandaDomain: String = "code.dev-gutools.co.uk"
override def pandaAuthCallback: String = "https://campaign-central.code.dev-gutools.co.uk/oauthCallback"

override def tagManagerApiUrl = "https://tagmanager.code.dev-gutools.co.uk/hyper"
override def tagManagerApiUrl = "https://tagmanager.code.dev-gutools.co.uk"
override def composerUrl = "https://composer.code.dev-gutools.co.uk"
override def liveUrl = "http://m.code.dev-theguardian.com"
override def previewUrl = "https://viewer.code.dev-gutools.co.uk/preview"
override def mediaAtomMakerUrl = "https://media-atom-maker.code.dev-gutools.co.uk"
override def ctaAtomMakerUrl = "https://cta-atom-maker.code.dev-gutools.co.uk"
}

class ProdConfig extends Config {
Expand All @@ -118,5 +133,10 @@ class ProdConfig extends Config {
override def pandaDomain: String = "gutools.co.uk"
override def pandaAuthCallback: String = "https://campaign-central.gutools.co.uk/oauthCallback"

override def tagManagerApiUrl = "https://tagmanager.gutools.co.uk/hyper"
override def tagManagerApiUrl = "https://tagmanager.gutools.co.uk"
override def composerUrl = "https://composer.gutools.co.uk"
override def liveUrl = "https://www.theguardian.com"
override def previewUrl = "https://viewer.gutools.co.uk/preview"
override def mediaAtomMakerUrl = "https://media-atom-maker.gutools.co.uk"
override def ctaAtomMakerUrl = "https://cta-atom-maker.gutools.co.uk"
}
1 change: 1 addition & 0 deletions conf/routes
Expand Up @@ -21,6 +21,7 @@ GET /api/campaigns controllers.CampaignApi.getAllCampaigns
GET /api/campaigns/:id controllers.CampaignApi.getCampaign(id: String)
PUT /api/campaigns/:id controllers.CampaignApi.updateCampaign(id: String)
GET /api/campaigns/:id/analytics controllers.CampaignApi.getCampaignAnalytics(id: String)
GET /api/campaigns/:id/content controllers.CampaignApi.getCampaignContent(id: String)
GET /api/campaigns/:id/notes controllers.CampaignApi.getCampaignNotes(id: String)
POST /api/campaigns/:id/notes controllers.CampaignApi.addCampaignNote(id: String)
PUT /api/campaigns/:id/note/:date controllers.CampaignApi.updateCampaignNote(id: String, date: String)
Expand Down
37 changes: 37 additions & 0 deletions public/actions/CampaignActions/getCampaignContent.js
@@ -0,0 +1,37 @@
import {fetchCampaignContent} from '../../services/CampaignsApi';

function requestCampaignContent(id) {
return {
type: 'CONTENT_GET_REQUEST',
id: id,
receivedAt: Date.now()
};
}

function recieveCampaignContent(content) {
return {
type: 'CONTENT_GET_RECIEVE',
campaignContent: content,
receivedAt: Date.now()
};
}

function errorRecievingCampaignContent(error) {
return {
type: 'SHOW_ERROR',
message: 'Could not get content',
error: error,
receivedAt: Date.now()
};
}

export function getCampaignContent(id) {
return dispatch => {
dispatch(requestCampaignContent(id));
return fetchCampaignContent(id)
.catch(error => dispatch(errorRecievingCampaignContent(error)))
.then(res => {
dispatch(recieveCampaignContent(res));
});
};
}
2 changes: 2 additions & 0 deletions public/components/Campaign/Campaign.js
@@ -1,5 +1,6 @@
import React, { PropTypes } from 'react';
import CampaignEdit from '../CampaignInformationEdit/CampaignEdit';
import CampaignAssets from '../CampaignInformationEdit/CampaignAssets';
import CampaignAnalytics from '../CampaignAnalytics/CampaignAnalytics';

class Campaign extends React.Component {
Expand All @@ -18,6 +19,7 @@ class Campaign extends React.Component {
<h2>{this.props.campaign.name}</h2>
<div className="campaign__row">
<CampaignEdit campaign={this.props.campaign} updateCampaign={this.props.campaignActions.updateCampaign} saveCampaign={this.props.campaignActions.saveCampaign}/>
<CampaignAssets campaign={this.props.campaign} />
<CampaignAnalytics campaign={this.props.campaign} />
</div>
</div>
Expand Down
22 changes: 22 additions & 0 deletions public/components/CampaignInformationEdit/CampaignAssets.js
@@ -0,0 +1,22 @@
import React, { PropTypes } from 'react';
import CampaignLevelAssets from './CampaignLevelAssets';
import CampaignContent from './CampaignContent';

class CampaignAssets extends React.Component {

render () {
return (
<div className="campaign-info campaign-box">
<div className="campaign-box__header">
Assets
</div>
<div className="campaign-box__body">
<CampaignLevelAssets campaign={this.props.campaign} />
<CampaignContent campaign={this.props.campaign} />
</div>
</div>
);
}
}

export default CampaignAssets;
121 changes: 121 additions & 0 deletions public/components/CampaignInformationEdit/CampaignContent.js
@@ -0,0 +1,121 @@
import React, {Component, PropTypes} from 'react';
import ProgressSpinner from '../utils/ProgressSpinner';
import {composerEditUrl, previewUrl, liveUrl, mediaAtomEditUrl} from '../../util/urlBuilder';

class CampaignContent extends Component {

componentWillMount() {
this.props.campaignContentActions.getCampaignContent(this.props.campaign.id);
}

componentWillReceiveProps(nextProps) {
if (nextProps.campaign.id !== this.props.campaign.id) {
this.props.campaignContentActions.getCampaignContent(nextProps.campaign.id);
}
}
renderContentAtoms = (atom) => {
return (
<div key={atom.id} className="campaign-content-list__row">
<div className="campaign-content-list__content-type"></div>
<div className="campaign-content-list__atom-title">{atom.type}: {atom.title}</div>
<div className="campaign-content-list__content-status"></div>
<div className="campaign-content-list__content-links">
<a href={mediaAtomEditUrl(atom.id)} target="_blank" title="Edit in atom builder"><i className="i-atom" /></a>
</div>
</div>
);
}

renderContentItem = (content) => {
var contentTypeIcon;

if (content.type === 'Article') {
contentTypeIcon = <i className="i-article" />
} else if (content.type === 'Gallery') {
contentTypeIcon = <i className="i-gallery" />
} else if (content.type === 'Video') {
contentTypeIcon = <i className="i-video" />
}

var status;
if(content.isLive) {
status = 'Live';
} else {
status = 'Draft';
}

return (
<div key={content.id} className="campaign-content-list__item">
<div className="campaign-content-list__row">
<div className="campaign-content-list__content-type">{contentTypeIcon}{content.type}</div>
<div className="campaign-content-list__content-title">{content.title}</div>
<div className="campaign-content-list__content-status">{status}</div>
<div className="campaign-content-list__content-links">
<a href={composerEditUrl(content.composerId)} target="_blank" title="Edit in composer"><i className="i-composer" /></a>
<a href={previewUrl(content.path)} target="_blank" title="Preview"><i className="i-preview-eye" /></a>
<a href={liveUrl(content.path)} target="_blank" title="See live"><i className="i-live-site" /></a>
</div>
</div>
{content.atoms.map( this.renderContentAtoms )}
</div>
);
}

renderContentItems = () => {

if(!this.props.campaignContent) {
return (<ProgressSpinner />);
}

if(this.props.campaignContent.length > 0) {
return (
<div className="campaign-content-list campaign-assets__field__value">
<div className="campaign-content-list__row">
<div className="campaign-content-list__content-type--header">Type</div>
<div className="campaign-content-list__content-title--header">Title</div>
<div className="campaign-content-list__content-status--header">Status</div>
<div className="campaign-content-list__content-links--header">Links</div>
</div>
{this.props.campaignContent.map( this.renderContentItem ) }
</div>
);
}

return (
<span className="campaign-assets__field__value">
No content has been created yet
</span>
)
}

render() {

return (
<div className="campaign-assets">
<div className="campaign-assets__field">
<label>Content</label>
{this.renderContentItems()}
</div>
</div>
);
}
}

//REDUX CONNECTIONS
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as getCampaignContent from '../../actions/CampaignActions/getCampaignContent';

function mapStateToProps(state) {
return {
campaignContent: state.campaignContent,
};
}

function mapDispatchToProps(dispatch) {
return {
campaignContentActions: bindActionCreators(Object.assign({}, getCampaignContent), dispatch)
};
}

export default connect(mapStateToProps, mapDispatchToProps)(CampaignContent);
61 changes: 61 additions & 0 deletions public/components/CampaignInformationEdit/CampaignLevelAssets.js
@@ -0,0 +1,61 @@
import React, { PropTypes } from 'react';
import {tagEditUrl, ctaEditUrl} from '../../util/urlBuilder'

class CampaignLevelAssets extends React.Component {

renderTagInformation = () => {

if(this.props.campaign.tagId) {
return (
<span className="campaign-assets__field__value">
<a href={tagEditUrl(this.props.campaign.tagId)} target="_blank">
<img src={this.props.campaign.campaignLogo} className="campaign-assets__field__logo"/>
{this.props.campaign.pathPrefix}
</a>
</span>
)
}

return (
<span className="campaign-assets__field__value">
No tag has been configured yet
</span>
)
}

renderCtaInformation = () => {

if(this.props.campaign.callToActions && this.props.campaign.callToActions.length > 0) {
return (
<span className="campaign-assets__field__value">
<ul>
{this.props.campaign.callToActions.map( cta => <li key={cta.builderId}><a href={ctaEditUrl(cta.builderId)} target="_blank">{cta.builderId}</a></li> )}
</ul>
</span>
)
}

return (
<span className="campaign-assets__field__value">
No call to actions configured yet
</span>
)
}

render () {
return (
<div className="campaign-assets">
<div className="campaign-assets__field">
<label>Tag</label>
{this.renderTagInformation()}
</div>
<div className="campaign-assets__field">
<label>Call to actions</label>
{this.renderCtaInformation()}
</div>
</div>
);
}
}

export default CampaignLevelAssets;

0 comments on commit 081370a

Please sign in to comment.