w
clone your own copy | download snapshot

Snapshots | iceberg

No images in this repository’s iceberg at this time

Inside this repository

models.js
application/javascript

Download raw (11.4 KB)

;
window.W = window.W || {};


;
(function (undefined) {

    // https://stackoverflow.com/a/2117523
    function uuidv4() {
        if (crypto && Uint8Array) {
            return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) {
                return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16);
            });
        } else {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }
    }

    // Part of transition should be removed later.
    var uuidMatch = /[\w\d]{8}\-[\w\d]{4}\-4[\w\d]{3}\-[\w\d]{4}\-[\w\d]{12}/g;

    /**
     * Loop through all sublines and set a type on them, to make the transition
     * to the linked axis data structure.
     * @param {Object} line 
     */
    function fixLines(line) {
        if ('target' in line) {
            line['type'] = 'link';

            /**
             * Method to filter out links?
             */
            if (!line['target'] || !line['target'].match(uuidMatch)) {
                return null;
            }
        } else {
            if (!('id' in line)) {
                line['id'] = uuidv4();
            }

            line['type'] = 'line';
            line['sublines'] = _.filter(_.map(line['sublines'], fixLines), function (l) { return (l !== null); });
        }

        return line;
    }

    'use strict';


    W.ChoiceModel = Backbone.Model.extend({});


    W.UserModel = Backbone.RelationalModel.extend({
        urlRoot: '/api/users/',

        label: function () {
            return this.get("username");
        },

        url: function () {
            var original_url = Backbone.Model.prototype.url.call(this);
            var parsed_url = original_url + (original_url.charAt(original_url.length - 1) == '/' ? '' : '/');

            return parsed_url;
        },
    });


    W.UserAuthModel = Backbone.Model.extend({
        urlRoot: '/rest-auth/user/',

        idAttribute: "pk",

        // defaults: {
        //     username: ""
        // },

        url: function () {
            var original_url = Backbone.Model.prototype.url.call(this);
            var parsed_url = original_url + (original_url.charAt(original_url.length - 1) == '/' ? '' : '/');

            return parsed_url;
        },

        isLoggedIn: function () {
            return this.model.id ? true : false
        }
    });


    // 
    // type null | file | video

    W.AttachmentModel = Backbone.RelationalModel.extend({
        defaults: {
            id: null,
            url: "",
            title: "",
            attachment: null,
        },

        urlRoot: '/api/attachments/',

        url: function () {
            var original_url = Backbone.Model.prototype.url.call(this);
            var parsed_url = original_url + (original_url.charAt(original_url.length - 1) == '/' ? '' : '/');

            return parsed_url;
        }
    })

    W.ScoreModel = Backbone.RelationalModel.extend({
        defaults: {
            title: "Untitled",
            mainline: {},
            stage_set: "aucune",
            setting: '',
            duration: '',
            genre: '',
            tags: '',
            score_type: 0,
            score_author: "",
            performance_author: "",
            presentation: "",
            effectif: "",
            language: "",
            permissions: {},
            shared_with: []
        },

        urlRoot: '/api/scores/',

        url: function () {
            var original_url = Backbone.Model.prototype.url.call(this);
            var parsed_url = original_url + (original_url.charAt(original_url.length - 1) == '/' ? '' : '/');

            return parsed_url;
        },

        relations: [
            {
                type: Backbone.HasOne,
                key: 'mainline',
                relatedModel: 'LineModel', // First line can not be a link
                reverseRelation: {
                    key: 'score',
                    includeInJSON: false,
                    type: Backbone.HasOne
                }
            },
            {
                type: Backbone.HasMany,
                key: 'permissions',
                relatedModel: 'PermissionModel',
                reverseRelation: {
                    key: 'score',
                    includeInJSON: false,
                    type: Backbone.HasOne
                }
            },
            {
                type: Backbone.HasMany,
                key: 'shared_with',
                relatedModel: 'UserModel',
                collectionType: 'UserCollection',
                reverseRelation: {
                    key: 'score',
                    includeInJSON: false,
                    type: Backbone.HasOne
                }
            }
        ],

        getDepth: function () {
            // Methode pour le vue "slider"
            // based on http://stackoverflow.com/questions/13523951/how-to-check-the-depth-of-an-object

            // var depthOf = function (object) {
            //     var level = 1;

            //     if (object.hasOwnProperty("sublines")) {
            //         for (var line in object.sublines) {
            //             var depth = depthOf(object.sublines[line]) + 1;
            //             level = Math.max(depth, level);
            //         }
            //     }

            //     return level
            // };

            // var json = this.toJSON();

            // return depthOf(json.mainline || json.sublines);
            return this.get('mainline').getDepth();
        },

        parse: function (data) {
            function trimStrings(v) {
                if (typeof v === "string") {
                    return v.trim();
                } else if (typeof v === "number") {
                    return v;
                } else if (v === null) {
                    return v;
                } else if (Array.isArray(v)) {
                    return _.map(v, trimStrings);
                } else if (typeof v === "object") {
                    return _.mapObject(v, trimStrings);
                }

                return v;
            }

            // console.log(data);
            data = trimStrings(data);

            if ("mainline" in data) {
                data.mainline = fixLines(data.mainline);
            }
            // console.log(data);
            return data;
        },
    });


    W.EntryModel = Backbone.RelationalModel.extend({
        subModelTypes: {
            'line': 'LineModel',
            'link': 'LinkModel'
        }
    });
    

    W.LineModel = W.EntryModel.extend({
        defaults: function () {
            return {
                sublines: [],
                // An id is necessary to make links to axes before they are saved.
                // Once models have an id they are managed by the collection.
                id: uuidv4(),
                title: t('axe principal'), //(uniq)
                contingent: false, // optionnel, au choix de l'interprète
                module_: false,
                aspect: '',
                //choix dans un array (duratif, itératif, sémelfactif)
                // duratif, l'action se déroule en continu
                // itératif, l'action est répétitive
                // sémelfactif l'action est ponctuelle
                piece_jointe: '', //url qui pointe vers un document
                terme: '', //(str)
                attachment: null,
                // boucle: on teste d'abord si boucle check est true
                // si oui y a t'il une durée de n à p
                // si non mettre n et p à 0
                // TODO: check if those 4 props can be merge in one

                // rangeType = enum{undetermined, exact, minimal, range}
                // null | { type: rangeType, value: null|number|[number, number]}
                boucle: null,

                // TODO: check if those 3 props can be merge in one
                // alternativeMode = enum { inclusive, exclusive}
                // null | { type: rangeType, mode: alternativeMode, value: null|number|[number, number]}
                alternative: null,
                // alternative_mode: '', //choix dans un array (exclusive, inclusive, conditionnelle) Validation importante des conditions dans une boucle inclusive
                // alternative_symbole: '',

                condition: '', // seulement valide si axe contingent ou si sous-axe d'une alternative
                imperative: false,
                tag: '', //Validation: peut avoir un tag seulement si l'axe      n'est pas principal, de plus le tag doit être le même pour ses siblings. Succession ordonnée, sans ordre, simultaméité, accumulation
                goto: null, //reference de l'axe vers lequel il renvoie
                focused: 0, // pas sûr que c'est l'endroit où mettre ceci.
                // Pas vraiment une propriété de l'objet.
                // Si l'objet est focused, il faut que la classe axis-focus
                // soit sur ses éléments handle et options.
                parent: null,
                actant: '', // string
                adresse: '', // string
                commandement: '', // string
                destination: '', // string
                code: '', // string
                indications: '' // long string
            };
        },

        getLevel: function () {
            var parent = this.get('parent');

            if (parent && parent.getLevel) {
                return parent.getLevel() + 1;
            }

            return 1;
        },

        getEditable: function () {
            var parent = this.get('parent');

            if (parent && parent.getEditable) {
                return parent.getEditable();
            }

            return this.get("score").get("is_editable");
        },

        getDepth: function () {
            return _.reduce(this.get('sublines').models, function (depth, line) { return Math.max(line.getDepth(), depth); }, 0) + 1;
        },

        getChildCount: function () {
            return this.get('sublines').length;
        },

        addSubLine: function () {
            var sublines = this.get('sublines');
            var title = "sous-axe " + (sublines.length + 1);
            var tag = (sublines.length > 0) ? sublines[0] : W.tags[0];
            sublines.add((new W.LineModel({ title: title, tag: tag })));
        },

        relations: [{
            type: Backbone.HasMany,
            key: 'sublines',
            relatedModel: 'EntryModel',
            collectionType: 'EntryCollection',
            reverseRelation: {
                key: 'parent',
                includeInJSON: false
            },
        },
        {
            type: Backbone.HasOne,
            key: 'attachment',
            relatedModel: W.AttachmentModel
        }]
    });

    W.LinkModel = W.EntryModel.extend({
        relations: [{
            type: Backbone.HasOne,
            key: 'target',
            includeInJSON: 'id',
            relatedModel: W.EntryModel
        }],

        getDepth: function () {
            return this.get('target').getDepth();
        },

        getLevel: function () {
            var parent = this.get('parent');

            if (parent && parent.getLevel) {
                return parent.getLevel() + 1;
            }

            return 1;
        }
    });

    W.PermissionModel = Backbone.RelationalModel.extend({
        defaults: {
            permissions: []
        },
    });
})();