|  | @@ -6,25 +6,77 @@ Boards.attachSchema(new SimpleSchema({
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    slug: {
 | 
	
		
			
				|  |  |      type: String,
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      // XXX We need to improve slug management. Only the id should be necessary
 | 
	
		
			
				|  |  | +      // to identify a board in the code.
 | 
	
		
			
				|  |  | +      // XXX If the board title is updated, the slug should also be updated.
 | 
	
		
			
				|  |  | +      // In some cases (Chinese and Japanese for instance) the `getSlug` function
 | 
	
		
			
				|  |  | +      // return an empty string. This is causes bugs in our application so we set
 | 
	
		
			
				|  |  | +      // a default slug in this case.
 | 
	
		
			
				|  |  | +      if (this.isInsert && !this.isSet) {
 | 
	
		
			
				|  |  | +        let slug = 'board';
 | 
	
		
			
				|  |  | +        const title = this.field('title');
 | 
	
		
			
				|  |  | +        if (title.isSet) {
 | 
	
		
			
				|  |  | +          slug = getSlug(title.value) || slug;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return slug;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    archived: {
 | 
	
		
			
				|  |  |      type: Boolean,
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isInsert && !this.isSet) {
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    createdAt: {
 | 
	
		
			
				|  |  |      type: Date,
 | 
	
		
			
				|  |  | -    denyUpdate: true,
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isInsert) {
 | 
	
		
			
				|  |  | +        return new Date();
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        this.unset();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    // XXX Inconsistent field naming
 | 
	
		
			
				|  |  |    modifiedAt: {
 | 
	
		
			
				|  |  |      type: Date,
 | 
	
		
			
				|  |  | -    denyInsert: true,
 | 
	
		
			
				|  |  |      optional: true,
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isUpdate) {
 | 
	
		
			
				|  |  | +        return new Date();
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        this.unset();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    // De-normalized number of users that have starred this board
 | 
	
		
			
				|  |  |    stars: {
 | 
	
		
			
				|  |  |      type: Number,
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isInsert) {
 | 
	
		
			
				|  |  | +        return 0;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    // De-normalized label system
 | 
	
		
			
				|  |  | +  'labels': {
 | 
	
		
			
				|  |  | +    type: [Object],
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isInsert && !this.isSet) {
 | 
	
		
			
				|  |  | +        const colors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
 | 
	
		
			
				|  |  | +        const defaultLabelsColors = _.clone(colors).splice(0, 6);
 | 
	
		
			
				|  |  | +        return defaultLabelsColors.map((color) => ({
 | 
	
		
			
				|  |  | +          color,
 | 
	
		
			
				|  |  | +          _id: Random.id(6),
 | 
	
		
			
				|  |  | +          name: '',
 | 
	
		
			
				|  |  | +        }));
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  |    'labels.$._id': {
 | 
	
		
			
				|  |  |      // We don't specify that this field must be unique in the board because that
 | 
	
		
			
				|  |  |      // will cause performance penalties and is not necessary since this field is
 | 
	
	
		
			
				|  | @@ -47,6 +99,19 @@ Boards.attachSchema(new SimpleSchema({
 | 
	
		
			
				|  |  |    // XXX We might want to maintain more informations under the member sub-
 | 
	
		
			
				|  |  |    // documents like de-normalized meta-data (the date the member joined the
 | 
	
		
			
				|  |  |    // board, the number of contributions, etc.).
 | 
	
		
			
				|  |  | +  'members': {
 | 
	
		
			
				|  |  | +    type: [Object],
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isInsert && !this.isSet) {
 | 
	
		
			
				|  |  | +        return [{
 | 
	
		
			
				|  |  | +          userId: this.userId,
 | 
	
		
			
				|  |  | +          isAdmin: true,
 | 
	
		
			
				|  |  | +          isActive: true,
 | 
	
		
			
				|  |  | +          isInvited: false,
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  |    'members.$.userId': {
 | 
	
		
			
				|  |  |      type: String,
 | 
	
		
			
				|  |  |    },
 | 
	
	
		
			
				|  | @@ -70,6 +135,11 @@ Boards.attachSchema(new SimpleSchema({
 | 
	
		
			
				|  |  |        'wisteria',
 | 
	
		
			
				|  |  |        'midnight',
 | 
	
		
			
				|  |  |      ],
 | 
	
		
			
				|  |  | +    autoValue() { // eslint-disable-line consistent-return
 | 
	
		
			
				|  |  | +      if (this.isInsert && !this.isSet) {
 | 
	
		
			
				|  |  | +        return Boards.simpleSchema()._schema.color.allowedValues[0];
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    description: {
 | 
	
		
			
				|  |  |      type: String,
 | 
	
	
		
			
				|  | @@ -338,41 +408,6 @@ if (Meteor.isServer) {
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Boards.before.insert((userId, doc) => {
 | 
	
		
			
				|  |  | -  // XXX We need to improve slug management. Only the id should be necessary
 | 
	
		
			
				|  |  | -  // to identify a board in the code.
 | 
	
		
			
				|  |  | -  // XXX If the board title is updated, the slug should also be updated.
 | 
	
		
			
				|  |  | -  // In some cases (Chinese and Japanese for instance) the `getSlug` function
 | 
	
		
			
				|  |  | -  // return an empty string. This is causes bugs in our application so we set
 | 
	
		
			
				|  |  | -  // a default slug in this case.
 | 
	
		
			
				|  |  | -  doc.slug = doc.slug || getSlug(doc.title) || 'board';
 | 
	
		
			
				|  |  | -  doc.createdAt = new Date();
 | 
	
		
			
				|  |  | -  doc.archived = false;
 | 
	
		
			
				|  |  | -  doc.members = doc.members || [{
 | 
	
		
			
				|  |  | -    userId,
 | 
	
		
			
				|  |  | -    isAdmin: true,
 | 
	
		
			
				|  |  | -    isActive: true,
 | 
	
		
			
				|  |  | -  }];
 | 
	
		
			
				|  |  | -  doc.stars = 0;
 | 
	
		
			
				|  |  | -  doc.color = Boards.simpleSchema()._schema.color.allowedValues[0];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Handle labels
 | 
	
		
			
				|  |  | -  const colors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
 | 
	
		
			
				|  |  | -  const defaultLabelsColors = _.clone(colors).splice(0, 6);
 | 
	
		
			
				|  |  | -  doc.labels = defaultLabelsColors.map((color) => {
 | 
	
		
			
				|  |  | -    return {
 | 
	
		
			
				|  |  | -      color,
 | 
	
		
			
				|  |  | -      _id: Random.id(6),
 | 
	
		
			
				|  |  | -      name: '',
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Boards.before.update((userId, doc, fieldNames, modifier) => {
 | 
	
		
			
				|  |  | -  modifier.$set = modifier.$set || {};
 | 
	
		
			
				|  |  | -  modifier.$set.modifiedAt = new Date();
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  if (Meteor.isServer) {
 | 
	
		
			
				|  |  |    // Let MongoDB ensure that a member is not included twice in the same board
 | 
	
		
			
				|  |  |    Meteor.startup(() => {
 |