src_js/iconolab-bundle/src/components/editor/AnnotationForm.vue
author Alexandre Segura <mex.zktk@gmail.com>
Tue, 02 May 2017 13:50:05 +0200
changeset 485 47080491b330
parent 483 dce041bc57a9
child 504 11a862e01b04
permissions -rw-r--r--
Add intro.js for on boarding.

<template>
    <div>
        <button
            data-intro="Proposez une nouvelle version" data-position="left"
            v-if="annotation && isAuthenticated" @click="readonly = !readonly"
            class="btn btn-xs pull-right"
            v-bind:class="{ 'btn-primary': readonly, 'btn-warning': !readonly }">
            <i class="fa fa-edit" v-if="readonly"></i>
            <span v-if="readonly">Modifier</span>
            <i class="fa fa-ban" v-if="!readonly"></i>
            <span v-if="!readonly">Annuler</span>
        </button>
        <div v-if="!annotation" class="alert alert-warning text-center">
            Aucune annotation sélectionnée
        </div>
        <form v-bind:action="formAction" method="post">
            <slot>
                <!-- CSRF token -->
            </slot>
            <input type="hidden" name="fragment" v-model="fragment">
            <div v-if="annotation" class="form-group form-group-sm">
                <label v-if="!readonly || title" class="small text-muted">Titre</label>
                <input type="text" class="form-control" name="title" v-model="title" v-if="!readonly">
                <p v-if="readonly && title" v-bind:class="{ 'text-muted': !title }">{{ title || 'Pas de titre' }}</p>
            </div>
            <div v-if="annotation" class="form-group form-group-sm">
                <label v-if="!readonly || description" class="small text-muted">Description</label>
                <textarea class="form-control" name="description" v-model="description" v-if="!readonly" placeholder="Décrivez ce que vous voyez"></textarea>
                <p v-if="readonly && description" v-bind:class="{ 'text-muted': !description }" v-html="descriptionComputed">{{ descriptionComputed || 'Pas de description' }}</p>
            </div>
            <div v-if="annotation" class="form-group form-group-sm">
                <label class="small text-muted">Mots-clés</label>
                <tag-list ref="taglist"
                    v-bind:original-tags="annotation.tags"
                    v-bind:readonly="readonly"
                    @change="onTagsChange($event.tags)"></tag-list>
                <input type="hidden" name="tags" v-model="serializedTags">
            </div>
            <p class="small text-center text-muted" v-if="annotation">
                <a v-bind:href="revisionsUrlComputed">Dernière version</a>
                <span>{{ dateComputed }} par</span>
                <a v-bind:href="authorUrlComputed">{{ annotation.author }}</a>
            </p>
            <button type="submit" v-if="annotation &amp;&amp; !readonly" v-bind:class="{ disabled: !hasChanged }"
                class="btn btn-block btn-sm btn-primary">Enregistrer une nouvelle version</button>
        </form>
    </div>
</template>

<script>

    import TagList from '../tagform/TagList.vue'
    import _ from 'lodash'
    import showdown from 'showdown'
    import moment from 'moment'

    const converter = new showdown.Converter()

    var defaults = {
        title: '',
        description: '',
        fragment: '',
        tags: [],
        readonly: true,
    }

    export default {
        props: {
            action: String,
            annotation: {
                type: Object,
                default: function () {
                    return null;
                }
            },
            isAuthenticated: {
                type: Boolean,
                default: false
            },
            revisionsUrl: String,
            authorUrl: String
        },
        components: {
            'tag-list': TagList
        },
        data() {
            return defaults;
        },
        mounted() {
            if (this.annotation) {
                this.loadAnnotation(this.annotation);
            }
        },
        watch: {
            annotation: function(annotation) {
                if (annotation) {
                    this.loadAnnotation(annotation);
                } else {
                    this.reset();
                }
            }
        },
        computed: {
            descriptionComputed: function() {
              return converter.makeHtml(this.description);
            },
            lastRevisionText: function() {
                if (this.annotation) {
                    var date = moment(this.annotation.created).locale('fr');
                    return 'Dernière version ' + date.fromNow() + ' par ' + this.annotation.author;
                }
            },
            revisionsUrlComputed: function() {
                if (this.annotation) {
                    return this.revisionsUrl.replace(':annotation_guid', this.annotation.annotation_guid);
                }
            },
            authorUrlComputed: function() {
                if (this.annotation) {
                    return this.authorUrl.replace('--username--', this.annotation.author);
                }
            },
            dateComputed: function() {
                if (this.annotation) {
                    return moment(this.annotation.created).locale('fr').fromNow();
                }
            },
            formAction: function() {
                if (this.annotation) {
                    return this.action.replace(':annotation_guid', this.annotation.annotation_guid);
                }
            },
            serializedTags: function() {
                var tags = this.tags.map(function(tag) {
                    return {
                        tag_input: (typeof tag.tag_link === "string" && tag.tag_link.length) ? tag.tag_link : tag.tag_label,
                        tag_label: tag.tag_label,
                        accuracy: tag.accuracy,
                        relevancy: tag.relevancy
                    }
                });

                return JSON.stringify(tags);
            },
            hasChanged: function() {
                if (!this.annotation) { return false; }

                return this.title !== this.annotation.title
                    || this.description !== this.annotation.description
                    || !_.isEqual(this.annotation.tags, this.tags);
            }
        },
        methods: {
            onTagsChange: function(tags) {
                this.tags = tags;
            },
            reset: function() {
                Object.assign(this, defaults);
            },
            loadAnnotation(annotation) {
                // Make sure we have an actual copy
                Object.assign(this, {
                    title: annotation.title,
                    description: annotation.description,
                    fragment: annotation.fragment,
                    tags: annotation.tags.slice(),
                    readonly: true,
                });
            }
        }
    }

</script>

<style scoped>
form {
    margin-bottom: 20px;
    clear: both;
}

label {
  font-weight: normal;
}
</style>