Rules I Follow

  • When it comes to JS and VueJS components, I make sure to keep them simple and clean.

  • I keep my components small to make development and debugging easier.

  • Structuring is everything! Click here for image

  • I am against dependencies when it comes to small implementations that can take a couple of hours to make. Adding 500KB to the APP just to use 1 feature from the library doesn't make any sense.

  • I use tools such as NuxtJS to make sure that my APP is fast and follows all the desired techniques to reduce size and provide a faster experience (SSR, minification, modular architecture, etc.)

VueJS Card component

<template>
  <div class="card">
    <d-header
      :question="question">
    </d-header>

    <d-body
      :question="question">
    </d-body>

    <d-footer
      v-if="question.attachedFiles.length > 0"
      :attachedFiles="question.attachedFiles">
    </d-footer>
  </div>
</template>

<script>
  import dHeader from './Header'
  import dBody from './Body'
  import dFooter from './Footer'

  export default {
    props: ['question'],

    components: {dHeader, dBody, dFooter}
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

VueJS Header component

<template>
  <div class="card-header">
    <edit-question-modal
      v-if="showEditQuestionModal"
      @close="showEditQuestionModal = false"
      :attachedFiles="question.attachedFiles">
    </edit-question-modal>

    <div class="row">
      <div
        :class="question.owner ? 'col-11' : 'col-12'">
        <h5 class="text-center">
          {{ question.question }}
        </h5>
      </div>

      <div class="col-1"
           v-if="question.owner">
        <div class="btn-group dropleft float-right">
          <i class="ellipsis" data-toggle="dropdown"></i>

          <div class="dropdown-menu">
            <button class="dropdown-item cursor-pointer"
                    @click="editMode()">
              Edit
            </button>

            <div class="dropdown-divider"></div>

            <button class="dropdown-item cursor-pointer"
                    @click="destroy()">
              Delete
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import {deleteForumQuestionMutation} from '../../../../graphql/requests/mutations/forumQuestion'
  import EditQuestionModal from '../../../../components/Forum/modals/Question/Modal'
  import {deletePopUp, toast} from '../../../../utilities/swal'

  export default {
    props: ['question'],

    components: {EditQuestionModal},

    data() {
      return {
        showEditQuestionModal: false
      }
    },

    methods: {
      editMode() {
        this.showEditQuestionModal = true

        this.$store.dispatch('setFormForumQuestion', {
          editing: true,
          question: this.question.question,
          content: this.question.content,
          tags: this.question.tags
        })
      },

      destroy() {
        deletePopUp('Are you sure you want to delete this forum question?').then(willDelete => {
          if (willDelete.value)
            deleteForumQuestionMutation(this, {variables: {slug: this.$route.params.slug}}).then(() => {
              this.$router.push('/forum')

              toast({type: 'success', title: 'Forum question has been deleted!'})
            })
        })
      }
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

VueJS Body component

<template>
  <div class="card-body">
    <pre class="white-space-normal"
         v-html="question.markdown_content"></pre>

    <div class="float-right">
      <span class="badge badge-dark"
            :class="index > 0 ? 'ml-3': ''"
            v-for="(tag, index) in question.tags">
        {{ tag.tag }}
      </span>
    </div>
  </div>
</template>

<script>
  export default {
    props: ['question']
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
  <div class="card-footer">
    <attached-source-code
      v-if="showAttachedSourceCodeModal"
      @close="showAttachedSourceCodeModal = false">
    </attached-source-code>

    <div class="text-center">
      <h6>
        Attached files
      </h6>

      <span class="p-2 border-radius-0-25 border cursor-pointer d-inline-block mr-3 mt-3" id="attachedFileText"
            data-toggle="modal" data-target="#attachedSourceCodeModal"
            v-for="attachedFile of attachedFiles"
            @click="setCurrentSourceCodeFile(attachedFile)">
      {{ attachedFile.name }}
    </span>
    </div>
  </div>
</template>

<script>
  import AttachedSourceCode from './modals/AttachedSourceCode/Modal'

  export default {
    props: ['attachedFiles'],

    components: {AttachedSourceCode},

    data() {
      return {
        showAttachedSourceCodeModal: false
      }
    },

    methods: {
      setCurrentSourceCodeFile(attachedFile) {
        this.showAttachedSourceCodeModal = true

        fetch(`${process.env.DEVLOB_URL}/highlight`, {
          method: 'post',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({id: attachedFile.id})
        }).
          then(response => response.json()).
          then(data => {
            this.$store.dispatch('setCurrentAttachedSourceCodeFile',
              {attachedFile: attachedFile, highlighted: data.highlighted})
          })
      }
    }
  }
</script>

<style scoped>
  #attachedFileText:hover {
    background-color: #FC503C;
    color: white;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64