+
+
+
+
+
diff --git a/deploy-key.enc b/deploy-key.enc
deleted file mode 100644
index 9f52705a..00000000
Binary files a/deploy-key.enc and /dev/null differ
diff --git a/docs/admin/collection.md b/docs/admin/collection.md
index 47914a1d..236b5f25 100644
--- a/docs/admin/collection.md
+++ b/docs/admin/collection.md
@@ -35,12 +35,21 @@ are explained below.
## Content
-A set of markdown editors are provided here for modifying content across the
-collection microsite, such as that which appears on the About, Contribute and
-Data pages.
+A set of markdown editors are provided here for modifying content for the About,
+Projects and Data pages. Changes are made in real-time, although you may have
+to refresh your browser to see them.
-Changes are made in real-time, although you may have to refresh your browser
-to see them.
+For the About page, navigation items will be generated from each level two
+header, created in Markdown by using the ## tag, for example:
+
+```
+## Contact
+
+This is the contact details section.
+```
+
+These navigation items can be clicked to scroll the users window to the top
+of that section.
For more guidance on the GitHub flavoured markdown used, see this
[GitHub Guide](https://guides.github.com/features/mastering-markdown/).
@@ -53,14 +62,25 @@ to objective, or task run to contribution.
## Tags
-The tags available for projects within the collection can be specified here.
-For each tag type created a new filter will be automatically added to the
-microsite's Contribute page (among others) so that users can more easily locate
-particular types of project.
+Tags are used to help users more easily location the types of project within a
+collection that they're interested in. For each tag type created via this
+admin section a new filter will be added to the microsite's Contribute
+page (among others).
+
+![Collection Admin - Tags](../assets/admin-collection-tags.png?raw=true)
+
+To add a new tag click the 'Add tag' button at the top of the table. You
+will then be given options to choose a tag type (e.g. Location), a tag name
+(e.g. London) and a colour. Note that the colour applies to all tags of the
+same type.
Once tags are created they can be added to individual projects via the
[Project Admin](admin/project.md) section.
+Tags can be edited or removed by locating them in the table and clicking the
+corresponding buttons. If you want to edit the color for a particular tag type
+just click edit on any tags of that type.
+
## Featured
Here you can set the projects that appear on the Featured Projects section of
diff --git a/docs/admin/project.md b/docs/admin/project.md
index b78735be..201a2cae 100644
--- a/docs/admin/project.md
+++ b/docs/admin/project.md
@@ -1 +1,42 @@
-# Project Admin
\ No newline at end of file
+# Project Admin
+
+Users with author or administrator rights can generate and manage projects via
+this interface.
+
+## Open Project
+
+To select the project that you wish to manage locate it in the table and click
+'Open'.
+
+## Settings
+
+The following core settings for a project can be edited here.
+
+| Setting | Description
+|------------------------------|-----------------------------------------------------------------------------------|
+| Name | The name of the project. |
+| Short name | Used as an identifier and to form URLs and filenames for data downloads. |
+| Description | Appears underneath the title on project cards. |
+| Webhook URL | URL to which a payload can be sent every time a task is completed. |
+| Password | An optional password for the project. |
+| Require a password | Projects that require a password will be hidden from the microsites public pages. |
+| Allow anonymous contributors | When switched off, only authenticated users will be able to contribute. |
+
+## Tags
+
+Tags are used to help users more easily location the types of project within a
+collection that they're interested in. You can choose one tag for each tag type.
+Contact an administrator if you need a tag that is not available.
+
+After choosing your tags and clicking 'Update' they will be added to project
+cards, tables and sorting options.
+
+## Collection
+
+Choose the collection microsite to which this project belongs by locating it
+in the table and clicking 'Select'
+
+## Thumbnail
+
+Use the file input to select an image to crop and use as a thumbnail on project
+cards.
diff --git a/docs/admin/site.md b/docs/admin/site.md
index d22f53ea..22119cc0 100644
--- a/docs/admin/site.md
+++ b/docs/admin/site.md
@@ -1,3 +1,45 @@
# Site Admin
-The settings are only available to administrators
\ No newline at end of file
+The site admin section comprises a set of pages where administrators can
+monitor activity on the platform, make global announements and manage users.
+
+## Dashboard
+
+The dashboard provides an overview of activity on the platform over the
+preceeding week. The charts include information about:
+
+- New, returning and active users;
+- New tasks and contributions;
+- Projects created, published and updated.
+
+Statistics are updated every 24 hours, but if you want to see the most recent
+data you can click the 'Refresh' button.
+
+## Users
+
+This is the section for managing all user related data. The toolbar at the top
+of the table provides options to search by name, or filter by various other
+attributes such as user permissions.
+
+To view and edit data for a particular user, for instance, to set permissions or
+checking by what method they signed up, locate them in the table and click
+'Open'.
+
+To export all registered users to CSV click the export button.
+
+## Announcements
+
+Here you can deliver global announcements to all users, which will be shown on
+the main navigation bars throughout the platform.
+
+The make an announcment click 'New', write the content (keep it short) and
+enter an internal or external URL. After clicking 'Submit' you will be taken
+to the update page where you can choose a thumbnail and publish the
+announcement.
+
+## Background Tasks
+
+The platform runs a range of sceduled tasks in the background for things such
+as email delivery, updating statistics and building data files. The interface
+provided here can be useful for diagnosing issues if any of these things don't
+appear to be working correctly (check the failed tasks list).
diff --git a/docs/administration.md b/docs/administration.md
deleted file mode 100644
index a90ac336..00000000
--- a/docs/administration.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Administration
-
-Administrators can access these settings via the main navigation bar.
-
-## Featured Projects
-
-Featured projects will appear on the homepage of the microsite that they belong to, as well as in the categories menu on the contribute page.
-
-To feature or un-feature a project locate it by category and click the **Add to featured** or **Remove from featured** buttons.
-
-![Admin - Featured Projects](./assets/admin-featured.png?raw=true)
-
-The page also provides a list of currently featured projects.
-
-## Collections
-
-Categories for all microsites are created via the **New Category** section and edited or deleted via the **Current Categories** section.
-
-### Tags
-
-Tags are used to organise projects and filter projects by multiple criteria. For
-example, a project can be tagged with the location *London* and task type
-*Transcription*, allowing user's to filter all projects that contain
-transcription tasks related to London.
-
-Each tag is given a **name** and a **type**. For each unique type, a
-multi-select sorting field will be made available alongside the lists of
-projects presented to users.
-
-## Users
-
-To manage user administrator rights, search for the user by name and click the **Grant admin rights** or **Revoke admin rights** buttons.
-
-To download all user data click the **Export to CSV** or **Export to JSON** buttons.
-
-![Admin - Manage Users](./assets/admin-users.png?raw=true)
-
-The page also provides a list of current administrators.
-
-## Announcements
-
-This section can make global announcements to all users, for example, when you want to draw attention to a new project.
-
-## Background Tasks
-
-All background tasks currently running on the server can be monitored via this page.
-
-![Admin - Background Tasks](./assets/admin-background-jobs.png?raw=true)
diff --git a/docs/assets/admin-background-jobs.png b/docs/assets/admin-background-jobs.png
deleted file mode 100644
index 13b1a649..00000000
Binary files a/docs/assets/admin-background-jobs.png and /dev/null differ
diff --git a/docs/assets/admin-categories.png b/docs/assets/admin-categories.png
deleted file mode 100644
index 22db96e8..00000000
Binary files a/docs/assets/admin-categories.png and /dev/null differ
diff --git a/docs/assets/admin-collection-featured.jpg b/docs/assets/admin-collection-featured.jpg
deleted file mode 100644
index 86727c75..00000000
Binary files a/docs/assets/admin-collection-featured.jpg and /dev/null differ
diff --git a/docs/assets/admin-collection-tags.png b/docs/assets/admin-collection-tags.png
new file mode 100644
index 00000000..e0f31d17
Binary files /dev/null and b/docs/assets/admin-collection-tags.png differ
diff --git a/docs/assets/admin-edit-categories-success.png b/docs/assets/admin-edit-categories-success.png
deleted file mode 100644
index a655293a..00000000
Binary files a/docs/assets/admin-edit-categories-success.png and /dev/null differ
diff --git a/docs/assets/admin-edit-categories.png b/docs/assets/admin-edit-categories.png
deleted file mode 100644
index 2d904277..00000000
Binary files a/docs/assets/admin-edit-categories.png and /dev/null differ
diff --git a/docs/assets/admin-featured.png b/docs/assets/admin-featured.png
deleted file mode 100644
index 1bfc0efc..00000000
Binary files a/docs/assets/admin-featured.png and /dev/null differ
diff --git a/docs/assets/admin-menu.png b/docs/assets/admin-menu.png
deleted file mode 100644
index 62866372..00000000
Binary files a/docs/assets/admin-menu.png and /dev/null differ
diff --git a/docs/assets/admin-users.png b/docs/assets/admin-users.png
deleted file mode 100644
index 12ea5246..00000000
Binary files a/docs/assets/admin-users.png and /dev/null differ
diff --git a/docs/configuration.md b/docs/configuration.md
index 9f673de5..01aa41c8 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -39,6 +39,11 @@ USER_INFO_PUBLIC_FIELDS = [
'announcements'
]
+# Additional project fields
+PROJECT_INFO_PUBLIC_FIELDS = [
+ 'tags'
+]
+
# Avoid 404 errors when accessing URLs with or without a trailing slash
STRICT_SLASHES = False
@@ -64,7 +69,8 @@ cp local.config.js.tmpl local.config.js
### analytics
-Add [Google Analytics](https://analytics.google.com).
+Add [Google Analytics](https://analytics.google.com) to the platform by
+providing your tracking ID.
```js
config.analytics = {
@@ -72,6 +78,29 @@ config.analytics = {
}
```
+[Event tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/events)
+will be enabled for the following:
+
+| Category | Action | Label | Description |
+|---------------|-----------------|-----------------|-----------------------------|
+| Downloads | {type}_{format} | Project name | Data file is downloaded |
+| Statistics | view | Project name | Project statistics viewed |
+| Contributions | {project name} | Collection name | Answer submitted |
+| Sorts | {sort value} | Collection name | Main projects list sorted |
+| Filters | {filter value} | Collection name | Main projects list filtered |
+
+Tracking these events can help to determine the content that your users are most
+interested in. For example, monitoring the filters most used for a microsite can
+help determine the types of project that should be prioritised for release at
+any given time.
+
+[Social interactions](https://developers.google.com/analytics/devguides/collection/analyticsjs/social-interactions)
+will be tracked using the social media 'Share' buttons present on the site.
+However, note that this reports button clicks and does not guarantee that the
+user actually then went ahead and shared the page.
+
+User IDs are used to track all registered and authenticated users.
+
### brand
Establish the brand.
diff --git a/docs/development.md b/docs/development.md
index e1b00019..74edd8f8 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -43,6 +43,9 @@ For cookies to be read properly you must access the website at http://127.0.0.1:
## Testing
``` bash
+# build (required for testing with nuxt components)
+npm run build
+
# run lint
npm lint
diff --git a/layouts/account-dashboard.vue b/layouts/account-dashboard.vue
index 731b88d0..c08dcddc 100644
--- a/layouts/account-dashboard.vue
+++ b/layouts/account-dashboard.vue
@@ -9,6 +9,8 @@ import localConfig from '@/local.config'
import DashboardBase from '@/layouts/bases/Dashboard'
export default {
+ middleware: 'is-current-or-admin',
+
components: {
DashboardBase
},
diff --git a/layouts/admin-collection-dashboard.vue b/layouts/admin-collection-dashboard.vue
index 2bcc476e..135598d4 100644
--- a/layouts/admin-collection-dashboard.vue
+++ b/layouts/admin-collection-dashboard.vue
@@ -10,6 +10,8 @@ import localConfig from '@/local.config'
import DashboardBase from '@/layouts/bases/Dashboard'
export default {
+ middleware: 'is-admin',
+
data () {
return {
rootNavItems: [
diff --git a/layouts/admin-project-dashboard.vue b/layouts/admin-project-dashboard.vue
index 110ea0ac..7abac5e0 100644
--- a/layouts/admin-project-dashboard.vue
+++ b/layouts/admin-project-dashboard.vue
@@ -10,6 +10,8 @@ import localConfig from '@/local.config'
import DashboardBase from '@/layouts/bases/Dashboard'
export default {
+ middleware: 'is-admin',
+
data () {
return {
rootNavItems: [
diff --git a/layouts/admin-site-dashboard.vue b/layouts/admin-site-dashboard.vue
index 4c736df6..b4ef3207 100644
--- a/layouts/admin-site-dashboard.vue
+++ b/layouts/admin-site-dashboard.vue
@@ -9,6 +9,8 @@ import localConfig from '@/local.config'
import DashboardBase from '@/layouts/bases/Dashboard'
export default {
+ middleware: 'is-admin',
+
data () {
return {
navItems: [
diff --git a/middleware/auth.js b/middleware/auth.js
index 8393aa9b..e9baf0da 100644
--- a/middleware/auth.js
+++ b/middleware/auth.js
@@ -16,6 +16,6 @@ export default function ({ isClient, store, req, app }) {
}
if (update && app.hasOwnProperty('$axios')) {
- store.dispatch('UPDATE_CURRENT_USER', app.$axios)
+ store.dispatch('UPDATE_CURRENT_USER', app.$axios, app.$ga)
}
}
diff --git a/middleware/is-admin.js b/middleware/is-admin.js
index beef5f0b..8059847f 100644
--- a/middleware/is-admin.js
+++ b/middleware/is-admin.js
@@ -5,10 +5,10 @@ import isEmpty from 'lodash/isEmpty'
* @param {Object} context
* The nuxt context.
*/
-export default function ({ app, store, route, redirect, error }) {
+export default function ({ store, redirect, error }) {
const currentUser = store.state.currentUser
- if (isEmpty(currentUser)) {
- redirect(`/account/signin?next=${route.path}`)
+ if (!currentUser || isEmpty(currentUser)) {
+ redirect(`/account/signin`)
} else if (!currentUser.admin) {
error({
message: 'Forbidden',
diff --git a/middleware/is-current-or-admin.js b/middleware/is-current-or-admin.js
new file mode 100644
index 00000000..e2fdce6e
--- /dev/null
+++ b/middleware/is-current-or-admin.js
@@ -0,0 +1,19 @@
+import isEmpty from 'lodash/isEmpty'
+
+/**
+ * Middleware to check if the current user is admin or the owner of a page.
+ * @param {Object} context
+ * The nuxt context.
+ */
+export default function ({ store, route, redirect, error }) {
+ const name = route.params.name
+ const currentUser = store.state.currentUser
+ if (isEmpty(currentUser)) {
+ redirect(`/account/signin?next=${route.path}`)
+ } else if (!currentUser.admin && !currentUser.name === name) {
+ error({
+ message: 'Forbidden',
+ statusCode: 403
+ })
+ }
+}
diff --git a/mixins/computeNext.js b/mixins/computeNext.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/mixins/computeTags.js b/mixins/computeTags.js
deleted file mode 100644
index 91bb3641..00000000
--- a/mixins/computeTags.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Method to batch tags for the current collection by type.
- *
- * Adds a key by which the tag can later be identified.
- */
-export const computeTags = {
- computed: {
- tags () {
- const batches = []
- const tags = this.$store.state.currentCollection.info.tags
- const uniqueTypes = [...new Set(tags.map(tag => tag.type))]
- for (let type of uniqueTypes) {
- batches.push({
- type: type,
- key: `tag:${encodeURI(type.replace(/\s+/g, '_').toLowerCase())}`,
- options: tags.filter(tag => {
- return tag.type === type
- })
- })
- }
- return batches
- }
- }
-}
diff --git a/mixins/deleteDomainObject.js b/mixins/deleteDomainObject.js
index aebe3638..44e014cd 100644
--- a/mixins/deleteDomainObject.js
+++ b/mixins/deleteDomainObject.js
@@ -15,11 +15,7 @@ export const deleteDomainObject = {
return this.$axios.$delete(`/api/${type}/${id}`)
}
}).then(data => {
- this.notify({
- type: 'success',
- title: 'Success',
- message: `${capitalize(terminology)} deleted`
- })
+ this.notifySuccess({ message: `${capitalize(terminology)} deleted` })
callback()
}, (dismiss) => {
this.$swal.close()
diff --git a/mixins/exportFile.js b/mixins/exportFile.js
new file mode 100644
index 00000000..46a30703
--- /dev/null
+++ b/mixins/exportFile.js
@@ -0,0 +1,25 @@
+import FileSaver from 'file-saver'
+
+export const exportFile = {
+ methods: {
+ /**
+ * Export data as a zip file.
+ * @param {data} data
+ * The data.
+ * @param {String} prefix
+ * The filename prefix.
+ * @param {String} format
+ * The data format.
+ */
+ exportFile (data, prefix, format) {
+ const types = {
+ 'zip': 'application/zip',
+ 'csv': 'text/csv',
+ 'json': 'application/json'
+ }
+ const blob = new Blob([data], { type: types[format] })
+ const fn = `${prefix}.${format}`
+ return FileSaver.saveAs(blob, fn)
+ }
+ }
+}
diff --git a/mixins/filterProjects.js b/mixins/filterProjects.js
new file mode 100644
index 00000000..bf7eb745
--- /dev/null
+++ b/mixins/filterProjects.js
@@ -0,0 +1,54 @@
+/**
+ * A mixin for filtering projects.
+ */
+export const filterProjects = {
+ data () {
+ return {
+ showCompleted: true,
+ tagModel: {}
+ }
+ },
+
+ computed: {
+ filteredProjects () {
+ // Check tags
+ let filtered = this.projects.filter(project => {
+ for (let key of Object.keys(this.tagModel)) {
+ project.info.tags = project.info.tags || {}
+ if (project.info.tags[key] !== this.tagModel[key]) {
+ return false
+ }
+ }
+ return true
+ })
+
+ if (this.showCompleted) {
+ return filtered
+ }
+
+ // Filter completed
+ return filtered.filter(project => {
+ return project.overall_progress < 100
+ })
+ }
+ },
+
+ methods: {
+ /**
+ * Set a tag type in the tag model.
+ * @param {String} type
+ * The type.
+ * @param {String} value
+ * The value.
+ */
+ updateTagModel (type, value) {
+ this.tagModel[type] = value
+ // Create a new object to trigger changes
+ this.tagModel = Object.assign({}, this.tagModel)
+ },
+
+ clearFilters () {
+ this.tagModel = Object.assign({})
+ }
+ }
+}
diff --git a/mixins/licenses.js b/mixins/licenses.js
new file mode 100644
index 00000000..909196d7
--- /dev/null
+++ b/mixins/licenses.js
@@ -0,0 +1,43 @@
+/**
+ * A mixin for the available licenses for data reuse, and their URLs.
+ */
+export const licenses = {
+ data () {
+ const baseUrl = 'https://creativecommons.org/licenses'
+ const version = '4.0'
+ return {
+ dataLicenses: {
+ CC0: {
+ id: 'CC0',
+ name: 'CC0',
+ url: 'https://creativecommons.org/publicdomain/zero/1.0/'
+ },
+ CC_BY: {
+ name: 'CC0',
+ url: `${baseUrl}/by/${version}/`
+ },
+ CC_BY_SA: {
+ name: 'CC BY-SA',
+ url: `${baseUrl}/by-sa/${version}/`
+ },
+ CC_BY_ND: {
+ name: 'CC BY-ND',
+ url: `${baseUrl}/by-nd/${version}/`
+ },
+ CC_BY_NC: {
+ name: 'CC BY-NC',
+ url: `${baseUrl}/by-nc/${version}/`
+ },
+
+ CC_BY_NC_SA: {
+ name: 'CC BY-NC-SA',
+ url: `${baseUrl}/by-nc-sa/${version}/`
+ },
+ CC_BY_NC_ND: {
+ name: 'CC_BY-NC-ND',
+ url: `${baseUrl}/by-nc-nd/${version}/`
+ }
+ }
+ }
+ }
+}
diff --git a/mixins/loadCollectionFeatured.js b/mixins/loadCollectionFeatured.js
deleted file mode 100644
index c7836891..00000000
--- a/mixins/loadCollectionFeatured.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import merge from 'lodash/merge'
-
-export const loadCollectionFeatured = {
- data () {
- return {
- featured: []
- }
- },
-
- methods: {
- loadCollectionFeatured () {
- let projects = []
- this.$axios.$get('/api/project', {
- params: {
- category_id: this.collection.id,
- featured: true,
- all: 1
- }
- }).then(data => {
- projects = data
- return this.$axios.$get('/api/projectstats', {
- params: {
- project_id: data.map(project => project.id).toString()
- }
- })
- }).then(data => {
- this.featured = projects.map((project, idx) => {
- return merge(data[idx], project)
- })
- }).catch(err => {
- this.$nuxt.error(err)
- })
- }
- }
-}
diff --git a/mixins/notifications.js b/mixins/notifications.js
index 6142617d..de8a9a31 100644
--- a/mixins/notifications.js
+++ b/mixins/notifications.js
@@ -5,8 +5,29 @@ export const notifications = {
notify: {},
notifySuccess: {
title: 'Success',
+ type: 'success'
+ },
+ notifyWarn: {
+ title: 'Warning',
+ type: 'warn'
+ },
+ notifyInfo: {
+ title: 'Info',
+ type: 'info'
+ },
+ notifyError: {
+ title: 'Error',
+ type: 'error'
+ },
+ notifyInvalidForm: {
+ title: 'Invalid form data',
+ type: 'warn',
+ message: 'Please correct the errors'
+ },
+ notifyAnswerSaved: {
+ title: 'Answer saved',
type: 'success',
- message: ''
+ message: 'Thank you for your contribution!'
}
},
@@ -18,11 +39,19 @@ export const notifications = {
*/
flash (data) {
if (data !== undefined && 'flash' in data) {
- this.notify({
- title: capitalize(data.status),
- type: data.status,
- message: data.flash
- })
+ if (data.status === 'success') {
+ this.notifySuccess({ message: data.flash })
+ } else if (data.status === 'warning') {
+ this.notifyWarn({ message: data.flash })
+ } else if (data.status === 'info') {
+ this.notifyInfo({ message: data.flash })
+ } else {
+ this.notify({
+ title: capitalize(data.status),
+ type: data.status,
+ message: data.flash
+ })
+ }
}
}
}
diff --git a/nuxt.config.js b/nuxt.config.js
index 523968e3..62cc04f1 100644
--- a/nuxt.config.js
+++ b/nuxt.config.js
@@ -19,7 +19,7 @@ const config = {
css: [
'~/assets/style/main.scss',
'cookieconsent/build/cookieconsent.min.css',
- 'izitoast/dist/css/iziToast.min.css',
+ 'izitoast/dist/css/iziToast.css',
'vue-multiselect/dist/vue-multiselect.min.css',
'simplemde/dist/simplemde.min.css',
'libcrowds-viewer/dist/scss/main.scss'
diff --git a/pages/account/newsletter.vue b/pages/account/newsletter.vue
index e368445b..dd5fdbba 100644
--- a/pages/account/newsletter.vue
+++ b/pages/account/newsletter.vue
@@ -55,16 +55,25 @@ export default {
* True to subscribe, false otherwise.
*/
subscribe (subscribe) {
- const next = this.$route.query.next || '/'
- this.$axios.$get(`/account/newsletter`, {
- params: {
- subscribe: subscribe ? 'True' : 'False'
- }
- }).then(data => {
+ // We can't guarantee the format of the next param returned after OAuth
+ // so add an additional check that it is at least just a pathname.
+ const parser = document.createElement('a')
+ parser.href = this.$route.query.next || '/'
+ const next = parser.pathname
+
+ if (subscribe) {
+ this.$axios.$get(`/account/newsletter`, {
+ params: {
+ subscribe: 'True'
+ }
+ }).then(data => {
+ this.$router.push({ path: next })
+ }).catch(err => {
+ this.$nuxt.error(err)
+ })
+ } else {
this.$router.push({ path: next })
- }).catch(err => {
- this.$nuxt.error(err)
- })
+ }
}
}
}
diff --git a/pages/account/signin.vue b/pages/account/signin.vue
index f68f570b..6d80e0ae 100644
--- a/pages/account/signin.vue
+++ b/pages/account/signin.vue
@@ -9,7 +9,7 @@