Medialist / medialist-app2

:newspaper: Make your PR team smarter and faster with media lists that capture intelligence, cut admin hours and keep campaigns in sync.
http://medialist.io/
1 stars 1 forks source link

Medialist

Make your PR team smarter and faster with media lists that capture intelligence, cut admin hours and keep campaigns in sync.

Usage

With node npm & meteor installed

npm install
npm run watch

Data model

Example documents from our collections

Users

{
  "_id" : "CBdsCSdGr3X7pLwnJ",
  "createdAt" : ISODate("2017-01-04T16:00:03.904Z"),
  "emails": {
    { address: "unique@exampled.org", verified: true }
  },
  "services" : {
    "resume" : {
      "loginTokens" : [
        {
          "when" : ISODate("2017-01-04T16:00:03.913Z"),
          "hashedToken" : "osidnsoidvsodivsdoinsndoifjsdofijsjdf="
        }
      ]
    }
  },
  "profile" : {
    "name" : "Richard Silverton",
    "avatar": "http://path/to/image.png"
  },
  "myCampaigns": [
    {
      "_id": "eoriwoerijgworigjw409jgw4",
      "name": "The Next Big Thing",
      "slug": "next-big-thing",
      "avatar": "https://example.com/image.png",
      "clientName": "ABC Corp.",
      "updatedAt": ISODate("2017-01-04T15:38:14.882Z")
    }
  ],
  "myContacts": [
    {
      "_id": "3rohu349f840fj3049j34g",
      "name": "Andrea Person",
      "slug": "andrea-person",
      "avatar": "https://example.com/avatar.png",
      "updatedAt": ISODate("2017-01-04T15:38:14.882Z")
    }
  ]
  "roles": ['team']
}

Contacts

{
  "_id" : "22zjKES2iEkN9PTdD",
  "slug" : "SteveRose",
  "name" : "Steve Rose",
  "avatar" : "https://pbs.twimg.com/profile_images/530735370120331264/25YBKDB-_normal.jpeg",
  "outlets" : [
    { "label": "the Guardian", "value": "Freelance" },
    { "label": "the Guardian - g2 (supplement)", "value": "Features" }
  ],
  "emails" : [
    { "label" : "Email", "value" : "steverose7@gmail.com" }
  ],
  "socials" : [
    { "label" : "Twitter", "value" : "steverose7", "twitterId" : "109295079" }
  ],
  "phones" : [
    { "label" : "Mobile", "value" : "+44 (0)7980 327 310" }
  ],
  "address" : "53 Athenlay Road, London, SE15 3EN, United Kingdom",
  "campaigns" : [
    "campaign-slug-1", "campaign-slug-2"
  ],
  "tags": [
    { "_id": "xyz", "slug": "nice", "name": "Nice", "count": 9 }
  ],
  "masterLists": [
    { "_id": "123", "slug": "tech", "name": "Tech" }
  ],
  "imports": [
    "contact-import-id"
  ]
  "createdAt" : ISODate("2016-02-26T13:12:53.456Z"),
  "createdBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert",
    "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
  },
  "updatedAt" : ISODate("2016-02-26T13:12:53.456Z"),
  "updatedBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert",
    "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
  }
}

Campaigns

{
  "_id" : "54gbNST2YBuqbrB4T",
  "slug" : "amazonecho",
  "name" : "Amazon Echo",
  "client" : {
    "name" : "Amazon",
    "_id" : "iYurjZ3HbvmMbuRYr"
  },
  "purpose" : "Amazon is good for the UK",
  "contacts" : [
    {
      "slug": "eleanor-harding",
      "status": "To Contact",
      "latestPost": {
        "_id" : "2EnrcJ7r5i94JTmwZ",
        "type" : "campaigns changed",
        "//": "and the rest..."
      },
      "owners": [
        {
          "_id" : "hNc2ArK9TcAWyEXqQ",
          "name" : "Olly Gilbert",
          "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
        }
      ],
      // Coverage items are PostRef's
      "coverage": [{
        "_id" : "hNc2ArK9TcAWyEXqQ",
        "message": "How meta BBC news app on BBC news http://www.bbc.co.uk/mediacentre/worldnews/270712-bbc-news-app",
        "embeds": [{
          "_id" : "hNc2ArK9TcAWyEXqQ",
          "url": "http://www.bbc.co.uk/mediacentre/worldnews/270712-bbc-news-app",
          "outlet": "BBC",
          "headline": "BBC News app launches on Amazon’s Kindle Fire in the US",
          "image": "http://ichef.bbci.co.uk/corporate2/images/width/live/p0/0w/md/p00wmddm.jpg/624",
          "datePublished": ISODate("2016-02-24T22:26:39.782Z")
        }],
        "createdAt": ISODate("2016-02-24T22:26:39.782Z")
      }],
      "updatedAt": ISODate("2016-02-24T22:26:39.782Z"),
      "updatedBy": {
        "_id" : "hNc2ArK9TcAWyEXqQ",
        "name" : "Olly Gilbert",
        "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
      }
    }
  ],
  "tags": [
    { "_id": "xyz", "slug": "nice", "name": "Nice", "count": 9 }
  ],
  "masterLists": [
    { "_id": "123", "slug": "tech", "name": "Tech" }
  ],
  "createdAt" : ISODate("2016-02-24T22:26:39.782Z"),
  "createdBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert"
  },
  "updatedAt" : ISODate("2016-09-29T12:30:02.895Z"),
  "updatedBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert"
  }
}

Post

{
  "_id" : "2EnrcJ7r5i94JTmwZ",
  "type" : "campaigns changed",
  "details" : {
    "action" : "added"
  }
  "message" : "added Eleanor to #activeschools",
  "contacts" : [
    {
      "slug" : "EleanorHarding",
      "name" : "Eleanor Harding",
      "avatar" : "https://pbs.twimg.com/profile_images/674213477477691392/63oxEK6E_normal.jpg"
    }
  ],
  "campaigns" : [
    "activeschools"
  ],
  "createdBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert",
    "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
  },
  "createdAt" : ISODate("2016-03-08T11:14:22.670Z"),
  // Date post was pinned. Not boolean and different to createdAt because pinned
  // posts need to be ordered by most recently pinned and user can unpin/re-pin.
  "pinnedAt" : ISODate("2018-03-12T13:17:00.000Z"),
  "pinnedBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert",
    "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
  }
}

MasterList

{
  "type": "Contacts",
  "name": "Tech",
  "slug": "tech",
  "items": [
    "contact _id"
  ]
  "order": 0
}

ContactsImport

{
  "data": [/* ContactCreateSchema valid objects */]
  "results": {
    created: ["contact-id"],
    updated: ["contact-id"],
    failed: [/* ContactCreateSchema valid objects */]
  }
  "createdBy" : {
    "_id" : "hNc2ArK9TcAWyEXqQ",
    "name" : "Olly Gilbert",
    "avatar" : "https://pbs.twimg.com/profile_images/2592146782/85lbyv6dgv9o3s9b83fw_normal.jpeg"
  },
  "createdAt" : ISODate("2016-03-08T11:14:22.670Z"),
}

Getting a db dump from Mongo Atlas

Get access to the Mongo Atlas account, or ask a friend for a recent DB snapshot.

In the web ui, choose

Now untar the downloaded file. The dir you are left with isn't a mongodump as you might have been hoping for. It's a snapshop of the db data file, and it's intended for use in a replicaSet, so we've gotta get our local mongo to point at this dbpath at startup, and get it to behave like a single node replicaSet, like so:

mongod --dbpath <backup dir path here> --replSet ml

Then, in another shell, configure your local mongod to be the primary node.

mongo

> rs.initiate({_id: "ml", members: [{_id: 0, host: 'localhost:27017'}]})
ml:SECONDARY>

# wait a couple of seconds, while mongo holds an eleection for 1
ml:PRIMARY> exit

The replSet name can be anything you like, just use the same one in both steps.

Now your local mongo is running on a snapshot of the cluster db, with all that good data. Don't share it with other people, it's got real humans contact detail in. If it doesn't work, consult the docs: restore-replica-set-from-backup

Start your meteor app with the MONGO_URL var

MONGO_URL=mongodb://localhost/next npm run watch

Styling

Some Basscss plus custom atoms with postcss to build it. See client/main.css

Colours

Charcoal Royal blue Ultramarine blue Bleu de France

Font sizes

We've got loads of font sizes, and they don't follow a typescale, so f-xxxl through f-xxxxs is used to denote font size. Most of the site is f-md, f-sm and f-lg, while the more extreme sizes occur infrequently so this feel like the most natural way to model it.

.f-xxxl { font-size:25px }
.f-xxl { font-size:20px }
.f-xl { font-size:18px }
.f-lg { font-size:16px }
.f-md { font-size:15px }
.f-sm { font-size:14px }
.f-xs { font-size:13px }
.f-xxs { font-size:12px }
.f-xxxs { font-size:11px }
.f-xxxxs { font-size: 9px }

Spacing

So:

<div class='mb3 p2'>Woo woo</div>

You can have responsive padding and margins too using basscss-responsive-padding & basscss-responsive-margin

<div class='mx3 p1 sm-p2 md-px3'>Woo woo</div>

Due to inheritance/media queries the net padding applied on a large screen would be padding:3rem 2rem

Media queries

Using postcss-custom-media

Using this input.css:

@custom-media --breakpoint-sm (min-width: 40em);

@media (--breakpoint-sm) {
  /* styles for small (tablet) viewport or larger */
}

you will get:

@media (max-width: 40em) {
  /* styles for small viewport */
}

Tests

Integration

There is a browser test suite built using nightwatch.

To start the app, run the tests and then shut down the app run:

npm run test:browser

To run the tests without starting and stopping the app automatically, first start the app with the test configuration:

npm run watch:server:test

Then run the tests as usual:

npm run test:browser

Options

Test options are specified as environment variables.

BROWSER 'chrome' or 'firefox'
PARALLEL true or false

You will need a recent version of chrome or firefox installed.

Running individual integration tests

To specify a subset of tests to run, tag your tests and pass the tags to the test runner. For example to run tests with the contacts tag:

npm run test:browser -- --tag contacts

More generally anything after -- will be passed to the nightwatch executable.

or run a specific file and test case like

npm run test:browser -- \
--test tests/browser/tests/activity.js \
--testcase "Should prevent multiple postings of the same activity"

Infrastructure and Deployment

You can build and run medialist as Docker container.

docker build -t medialist .
docker run -p 3000:3000 -e "MONGO_URL=mongodb://<db url here>" -e "ROOT_URL=<deploy url here>" -e "METEOR_SETTINGS=$(cat settings.json)" medialist