Skip to content

Commit

Permalink
Merge pull request #48 from ExtensionEngine/release/2.4
Browse files Browse the repository at this point in the history
v2.4
  • Loading branch information
underscope authored Mar 30, 2018
2 parents 8684df2 + 563fb5f commit 4b08a4a
Show file tree
Hide file tree
Showing 73 changed files with 2,928 additions and 1,472 deletions.
8 changes: 7 additions & 1 deletion .activities-rc.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
"label": "Description",
"placeholder": "Click to add...",
"validate": { "rules": { "required": false, "max": 23 } }
}]
}],
"contentContainers": ["PAGE"]
}],
"contentContainers": [{
"type": "PAGE",
"label": "Page",
"multiple": false
}]
}]
}
102 changes: 68 additions & 34 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
#
# General server behavior
#

###########################
# General server behavior #
###########################

# Express app will listen on this port.
SERVER_PORT=3000
SERVER_URL=http://localhost:3000

#
# Database
#
POSTGRES_URI=postgres://<user>:<pass>@localhost:5432/cima_auth

#
# Security and authentication
#
############
# Database #
############

POSTGRES_URI=postgres://<user>:<pass>@localhost:5432/tailor


###############################
# Security and authentication #
###############################

# Origins allowed in CORS requests. Multiple origins can be listed by using
# comma as a separator. In development, this will typically match your webpack
# dev server address:
Expand All @@ -22,29 +28,57 @@ CORS_ALLOWED_ORIGINS=http://localhost:8080
AUTH_SALT_ROUNDS=10

# Session secret string.
AUTH_JWT_SECRET=<some secret string>

#
# Pagination
#
# Default page number.
CURRENT_PAGE=1
# Number of items loaded per page.
ITEMS_PER_PAGE=20

#
# Email
#
EMAIL_ADDRESS=[email protected]
EMAIL_USER=xxxxxx
EMAIL_PASSWORD=xxxxxxxx
AUTH_JWT_SECRET=


#########
# Email #
#########

EMAIL_ADDRESS=[email protected]
EMAIL_USER=
EMAIL_PASSWORD=
EMAIL_HOST=email-smtp.us-east-1.amazonaws.com

#
# Storage
#
STORAGE_KEY=<storage-identifier>
STORAGE_SECRET=<storage-secret>
STORAGE_REGION=<storage-region>
STORAGE_BUCKET=<storage-bucket>
STORAGE_PROVIDER=<storage-provider>

###########
# Storage #
###########

# amazon or filesystem
STORAGE_PROVIDER=filesystem

# Filesystem provider settings
STORAGE_PATH=

# Amazon provider settings
STORAGE_KEY=
STORAGE_SECRET=
STORAGE_REGION=
STORAGE_BUCKET=


#################
# Schema config #
#################

# In order to disable default schema, create custom schema and set this param
# to falsy value. Disabling default schema won't work if custom schema
# does not exist.
ENABLE_DEFAULT_SCHEMA=1


####################
# General settings #
####################

# String template that will be interpolated on the client using two route params,
# repositoryId and activityId.
PREVIEW_URL=https://myserver.com/repository/{repositoryId}/activity/{activityId}

# Terminal (forcefully enable color)
FORCE_COLOR=1

# Do not group published resources by outline item id.
# repository/id/resourceId* instead of repository/id/outlineId/resourceId*
FLAT_REPO_STRUCTURE=1
21 changes: 9 additions & 12 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,23 @@ const isDev = process.env.NODE_ENV === 'development';

module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: { sourceType: 'module' },
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: 'standard',
// https://github.com/Flet/eslint-config-semistandard
extends: 'semistandard',
// required to lint *.vue files
plugins: ['html'],
rules: {
// allow paren-less arrow functions
indent: ['error', 2, {
SwitchCase: 1,
// NOTE: Consistent indentation IS enforced;
// ESlint calculated indentation start IS NOT!
// https://eslint.org/docs/rules/indent#memberexpression
MemberExpression: 'off'
}],
'arrow-parens': 'off',
// warn if there is a trailing comma
'comma-dangle': ['warn', 'never'],
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': isDev ? 'warn' : 'error',
// allow dead code during development
'no-unreachable': isDev ? 'warn' : 'error',
// semicolons are necessary
'semi': ['warn', 'always'],
// add space before function parameters
'space-before-function-paren': ['error', {
anonymous: 'always',
named: 'never'
Expand Down
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Tailor

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/d6d198f9c56b4ca799b4624c5bb3e16c)](https://www.codacy.com/app/underscope/tailor?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=ExtensionEngine/tailor&amp;utm_campaign=Badge_Grade)
[![GitHub package version](https://img.shields.io/github/package-json/v/ExtensionEngine/tailor.svg)](https://github.com/ExtensionEngine/tailor/blob/develop/package.json#L3)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/d6d198f9c56b4ca799b4624c5bb3e16c?branch=develop)](https://www.codacy.com/app/underscope/tailor?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=ExtensionEngine/tailor&amp;utm_campaign=Badge_Grade)
[![codebeat badge](https://codebeat.co/badges/f577cd02-ad4f-464d-8afc-be153929703d)](https://codebeat.co/projects/github-com-extensionengine-tailor-develop)
[![Known Vulnerabilities](https://snyk.io/test/github/ExtensionEngine/tailor/badge.svg)](https://snyk.io/test/github/ExtensionEngine/tailor)
[![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard)
[![GitHub license](https://img.shields.io/github/license/ExtensionEngine/tailor.svg)](https://github.com/ExtensionEngine/tailor/blob/develop/LICENSE)
[![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=102)](https://github.com/ellerbrock/open-source-badge/)

Adaptive course authoring platform.

Expand All @@ -25,7 +29,8 @@ Adaptive course authoring platform.
* App is configured via environment variables contained in a file named `.env`.
Use the `.env.example` file as a template: `cp .env.example .env` and enter
configuration details.
* You can init the db (for development) by running `npm run db:seed`
* You can init the db (for development) by setting `ENABLE_DEFAULT_SCHEMA=1`
and running `npm run db:seed`.
* You can create admin user by running `npm run add:admin <email> <password>`
* App branding is configured via values set in a file named `.brand-rc.json`.
Use the `.brand-rc.json.example` file as a template: `cp .brand-rc.json.example .brand-rc.json` and enter configuration details.
Expand Down Expand Up @@ -53,7 +58,9 @@ An array of Schema objects.
#### Schema
* **id** `String` - Schema identifier.
* **name** `String` - Schema display name.
* **meta** `Array<Metadata>` - An array of objects defining repository metadata.
* **structure** `Array<ActivityConfig>` - An array of objects which define schema structure.
* **contentContainers** `Array<ContentContainer>` - Array of content container configs

#### ActivityConfig - Schema structure elements
Configuration for schema structure nodes (activities). Contains the following properties:
Expand All @@ -62,21 +69,21 @@ Configuration for schema structure nodes (activities). Contains the following pr
* **subLevels** `Array<String>` - An array of sub-types.
* **label** `String` - Display label.
* **color** `String` - Display color in hexadecimal notation.
* **isEditable** `Boolean` - Activity allows adding activities/teaching elements to it.
* **contentContainers** `Array<String>` - Array of content container types that define which content containers can be added.
* **hasAssessments** `Boolean` - Activity allows adding assessments activities to it.
* **hasExams** `Boolean` - Activity allows adding exam activities to it.
* **exams** `Object` - Configuration for activity exams.
* **hasPrerequisites** `Boolean` - Defines if this activity should offer other activities as prerequisites.
* **meta** `Array<ActivityMetadata>` - An array of objects defining activity metadata.
* **meta** `Array<Metadata>` - An array of objects defining activity metadata.

#### ActivityMetadata
#### Metadata
Defines the structure of an activity metadata field.
* **key** `String`- Unique key for the field.
* **type** `String`- Type of the input component used on the client.
* **label** `String`- Display label.
* **placeholder** `String`- Input component placeholder.
* **validate** `MetadataValidator`- Validator object.
* **defaultValue** `*`- Default field value.

#### MetadataValidator
Defines validation rules on an activity metadata field.
Expand All @@ -97,5 +104,5 @@ Configuration for content containers. Contains the following properties:
* **layout** `Boolean` - Defines if elements inside container can be placed two in a row. True by default.

### `PREVIEW_URL`
A string template that will be interpolated on the client using two route params, `courseId` and `activityId`, into a preview URL for each activiy. Example:
`https://my.url.com/#/course/{courseId}/activity/{activityId}/preview`
A string template that will be interpolated on the client using two route params, `repositoryId` and `activityId`, into a preview URL for each activiy. Example:
`https://my.url.com/#/repository/{repositoryId}/activity/{activityId}/preview`
10 changes: 10 additions & 0 deletions client/api/activity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import request from './request';

function getActivities(courseId, params) {
return request.get(`/courses/${courseId}/activities`, { params })
.then(res => res.data.data);
}

export default {
getActivities
};
11 changes: 8 additions & 3 deletions client/api/course.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ const url = {
users: (courseId, userId = '') => `/courses/${courseId}/users/${userId}`
};

function getCourses(params) {
return request.get('/courses', { params }).then(res => res.data.data);
}

function getUsers(courseId, params) {
return request
.get(url.users(courseId), { params })
.then(res => res.data.data);
};
}

function upsertUser(courseId, data) {
return request
Expand All @@ -28,13 +32,14 @@ function getContentInventory(courseId) {
responseType: 'arraybuffer',
url: `/courses/${courseId}/contentInventory`
}).then(res => res.data);
};
}

function publishRepositoryMeta(id) {
return request.post(`/courses/${id}/publish`).then(res => res.data);
};
}

export default {
getCourses,
getUsers,
upsertUser,
removeUser,
Expand Down
4 changes: 4 additions & 0 deletions client/assets/stylesheets/common/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ $fab-font-size: 18px;
border-radius: 50%;
box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, 0.12), 0 1px 1px 0 rgba(0, 0, 0, 0.24);

&:focus {
outline: none;
}

.fa {
position: absolute;
top: 50%;
Expand Down
8 changes: 4 additions & 4 deletions client/components/catalog/Card/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@
</template>

<script>
import { getOutlineLevels } from 'shared/activities';
import { getObjectives } from 'shared/activities';
import Acronym from 'components/common/Acronym';
import get from 'lodash/get';
import last from 'lodash/last';
import map from 'lodash/map';
import pluralize from 'pluralize';
import Stat from './Stat';
import truncate from 'truncate';
Expand All @@ -40,7 +39,8 @@ export default {
return truncate(this.course.description, 180);
},
objectiveLabel() {
return pluralize(last(getOutlineLevels(this.course.schema)).label);
const objectives = map(getObjectives(this.course.schema), 'label');
return objectives.length > 1 ? 'Objectives' : pluralize(objectives[0]);
},
assessments() {
return get(this.course, 'stats.assessments', 0);
Expand Down
Loading

0 comments on commit 4b08a4a

Please sign in to comment.