4minitz/4minitz

View on GitHub
imports/infoitem.js

Summary

Maintainability
C
1 day
Test Coverage
/**
 * A InfoItem is a sub-element of
 * a topic which has a subject,
 * a date when is was created
 * and a list of associated tags.
 */
import { Meteor } from 'meteor/meteor';
import { _ } from 'meteor/underscore';
import { formatDateISO8601 } from '/imports/helpers/date';
import { Random } from 'meteor/random';
import { User } from '/imports/user';
export class InfoItem {

    constructor(parentTopic, source) {
        if (!parentTopic || !source)
            throw new Meteor.Error('It is not allowed to create a InfoItem without the parentTopicId and the source');

        this._parentTopic = undefined;
        this._infoItemDoc = undefined;

        if (typeof parentTopic === 'object') {   // we have a topic object here.
            this._parentTopic = parentTopic;
        }
        if (!this._parentTopic) {
            throw new Meteor.Error('No parent Topic given!');
        }

        if (typeof source === 'string') {   // we may have an ID here.
            // Caution: findInfoItem returns a InfoItem-Object not the document itself!
            let infoItem = this._parentTopic.findInfoItem(source);
            source = infoItem._infoItemDoc;
        }

        if (!source.hasOwnProperty('createdInMinute')) {
            throw new Meteor.Error('Property createdInMinute of topicDoc required');
        }

        _.defaults(source, {
            itemType: 'infoItem',
            isNew: true,
            isSticky: false,
            labels: []
        });
        this._infoItemDoc = source;
    }

    // ################### static methods
    static isActionItem(infoItemDoc) {
        return (infoItemDoc.itemType === 'actionItem');
    }

    static isCreatedInMinutes(infoItemDoc, minutesId) {
        return (infoItemDoc.createdInMinute === minutesId);
    }

    // ################### object methods
    invalidateIsNewFlag() {
        this._infoItemDoc.isNew = false;
    }

    getId() {
        return this._infoItemDoc._id;
    }

    isSticky() {
        return this._infoItemDoc.isSticky;
    }

    isDeleteAllowed(currentMinutesId) {
        return this._infoItemDoc.createdInMinute === currentMinutesId;
    }

    toggleSticky() {
        this._infoItemDoc.isSticky = !this.isSticky();
    }

    getSubject() {
        return this._infoItemDoc.subject;
    }

    addDetails(minuteId, text) {
        if (text === undefined) text = '';

        let date = formatDateISO8601(new Date());
        if (!this._infoItemDoc.details) {
            this._infoItemDoc.details = [];
        }
        this._infoItemDoc.details.push({
            _id: Random.id(),
            createdInMinute: minuteId,
            createdAt: new Date(),
            createdBy: User.PROFILENAMEWITHFALLBACK(Meteor.user()),
            updatedAt: new Date(),
            updatedBy: User.PROFILENAMEWITHFALLBACK(Meteor.user()),
            date: date,
            text: text,
            isNew: true
        });
    }

    removeDetails(index) {
        this._infoItemDoc.details.splice(index, 1);
    }

    updateDetails(index, text) {
        if (text === '') {
            throw new Meteor.Error('invalid-argument', 'Empty details are not allowed. Use #removeDetails() ' +
                'to delete an element');
        }
        if (text !== this._infoItemDoc.details[index].text){
            this._infoItemDoc.details[index].date = formatDateISO8601(new Date());
            this._infoItemDoc.details[index].text = text;
            this._infoItemDoc.details[index].updatedAt = new Date();
            this._infoItemDoc.details[index].updatedBy = User.PROFILENAMEWITHFALLBACK(Meteor.user());
        }
    }

    getDetails() {
        if (!this._infoItemDoc.details) {
            this._infoItemDoc.details = [];
        }

        return this._infoItemDoc.details;
    }

    getDetailsAt(index) {
        if (!this._infoItemDoc.details || index < 0 || index >= this._infoItemDoc.details.length) {
            throw new Meteor.Error('index-out-of-bounds');
        }

        return this._infoItemDoc.details[index];
    }

    async save(callback) {
        callback = callback || function () {};

        try {
            let result = await this.saveAsync();
            callback(undefined, result);
        } catch (error) {
            callback(error);
        }
    }

    async saveAsync(insertPlacementTop = true) {
        // caution: this will update the entire topics array from
        // the parent minutes of the parent topic!
        if (!this._infoItemDoc._id) { // it is a new one
            this._infoItemDoc.createdAt = new Date();
            this._infoItemDoc.createdBy = User.PROFILENAMEWITHFALLBACK(Meteor.user());
        }
        this._infoItemDoc.updatedAt = new Date();
        this._infoItemDoc.updatedBy = User.PROFILENAMEWITHFALLBACK(Meteor.user());
        this._infoItemDoc._id = await this._parentTopic.upsertInfoItem(this._infoItemDoc, true, insertPlacementTop);
    }

    async saveAtBottom() {
        return this.saveAsync(false);
    }

    getParentTopic() {
        return this._parentTopic;
    }

    isActionItem() {
        return InfoItem.isActionItem(this._infoItemDoc);
    }

    getDocument() {
        return this._infoItemDoc;
    }

    setSubject(newSubject) {
        this._infoItemDoc.subject = newSubject;
    }

    /**
     *
     * @param labelIds {string[]}
     */
    addLabelsById(labelIds) {
        labelIds.forEach(id => {
            if (!this.hasLabelWithId(id)) {
                this._infoItemDoc.labels.push(id);
            }
        });
    }

    hasLabelWithId(labelId) {
        let i;
        for (i = 0; i < this._infoItemDoc.labels.length; i++) {
            if (this._infoItemDoc.labels[i] === labelId) {
                return true;
            }
        }
        return false;
    }

    getLabelsRawArray() {
        if (!this._infoItemDoc.labels) {
            return [];
        }
        return this._infoItemDoc.labels;
    }

    toString () {
        return 'InfoItem: ' + JSON.stringify(this._infoItemDoc, null, 4);
    }

    log () {
        console.log(this.toString());
    }

}