<commit_before><template>
<div
  class="columns fixed-page"
>
  <div
    class="column main-column"
  >
    <div
      class="news page"
      ref="body"
      v-scroll="onBodyScroll"
    >
      <div class="timeline-wrapper">
      <div class="timeline">
      <div
        class="empty-list has-text-centered"
        v-if="!loading.news && (!newsList || newsList.length === 0)"
      >
        {{ $t('news.no_news') }}
      </div>
      <div
        class="has-text-centered"
        v-if="loading.news"
      >
        <spinner />
      </div>

      <div
        :key="dayList.length > 0 ? dayList[0].created_at : ''"
        v-for="dayList in newsListByDay"
      >
        <div class="has-text-centered subtitle timeline-entry">
          <span class="big-dot"></span>
          {{ dayList.length > 0 ? formatDay(dayList[0].created_at) : ''}}
        </div>
        <div
          :key="'news-' + news.id"
          v-for="news in dayList"
        >
          <div
            :class="{
              'news-line': true,
              'timeline-entry': true,
              flexrow: true,
              selected: news.id === currentNewsId
            }"
            @click.prevent="onNewsSelected(news)"
          >
            <span :class="{
              dot: true,
              red: hasRetakeValue(news)
            }"></span>
            <span class="date flexrow-item">
              {{ formatTime(news.created_at) }}
            </span>

            <div class="flexrow-item task-type-wrapper">
              <task-type-name
                class="task-type-name"
                :task-type="buildTaskTypeFromNews(news)"
                :production-id="currentProduction.id"
              />
            </div>

            <div class="flexrow-item validation-wrapper">
              <validation-tag
                class="validation-tag"
                :task="buildTaskFromNews(news)"
                v-if="news.change"
              />
            </div>

            <div class="flexrow-item comment-content">
              <div>
                <div class="news-info flexrow">
                  <people-avatar
                    class="flexrow-item"
                    :person="personMap[news.author_id]"
                    :size="30"
                    :no-link="true"
                    v-if="personMap[news.author_id]"
                  />
                  <span
                    class="explaination flexrow-item"
                  >
                    <span class="strong person-name">
                      {{ personName(news) }}
                    </span>
                    <span>
                      {{ $t('news.commented_on') }}
                    </span>
                    <span class="strong">
                      {{ ' ' + news.project_name }} / {{ news.full_entity_name }}
                    </span>
                  </span>
                </div>
              </div>
            </div>
          </div>

          <div class="preview" v-if="news.preview_file_id">
            <div
              :class="{
                'news-line': true,
                'timeline-entry': true,
                flexrow: true,
                selected: news.id === currentNewsId
              }"
              @click.prevent="onNewsSelected(news)"
            >
              <span class="date flexrow-item">
              </span>
              <div class="flexrow-item task-type-wrapper">
              </div>
              <div class="flexrow-item validation-wrapper">
              </div>

              <div class="flexrow-item comment-content">
                <div>
                  <div class="news-info flexrow">
                    <people-avatar
                      class="flexrow-item"
                      :person="personMap[news.author_id]"
                      :size="30"
                      :no-link="true"
                      v-if="personMap[news.author_id]"
                    />
                    <span
                      class="explaination flexrow-item"
                    >
                      <span class="strong person-name">
                        {{ personName(news) }}
                      </span>
                      <span>
                        {{ $t('news.set_preview_on') }}
                      </span>
                      <span class="strong">
                        {{ ' ' + news.project_name }} / {{ news.full_entity_name }}
                      </span>
                    </span>
                  </div>
                </div>
              </div>
            </div>

            <div
              class="has-text-centered"
            >
              <div
                v-if="news.preview_file_extension == 'mp4'"
              >
                <video-player
                  :preview="{id: news.preview_file_id}"
                  :task-type-map="taskTypeMap"
                  :read-only="true"
                  :light="true"
                />
              </div>

              <model-viewer
                class="model-viewer"
                :preview-url="getPreviewPath(news)"
                :preview-dl-path="getPreviewDlPath(news)"
                :light="true"
                :read-only="true"
                v-else-if="news.preview_file_extension == 'obj'"
              />

              <picture-viewer
                :preview="{previews: [{id: news.preview_file_id}]}"
                :light="true"
                :read-only="true"
                ref="preview-picture"
                v-else-if="news.preview_file_extension == 'png'"
              />

              <div
                class="preview-standard-file"
                v-else
              >
                <a
                  class="button"
                  ref="preview-file"
                  :href="getPreviewDlPath(news)"
                >
                  <download-icon class="icon" />
                  <span class="text">
                    {{ $t('tasks.download_pdf_file', {extension: news.preview_file_extension}) }}
                  </span>
                </a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  </div>
  </div>

  <div
    class="column side-column is-hidden-mobile hide-small-screen"
    v-if="currentTask"
  >
    <task-info
      :task="currentTask"
      :is-loading="loading.currentTask"
    />
  </div>
</div>

</template>

<script>
/*
 * This modules aims at displaying what happened on the production during the
 * last few days.
 * News entry are fetched by page of 50. Loading of older news is done via
 * infinite scrolling.
 */
import { mapGetters, mapActions } from 'vuex'
import {
  DownloadIcon
} from 'vue-feather-icons'
import moment from 'moment-timezone'

import EntityThumbnail from '../widgets/EntityThumbnail'
import ModelViewer from '../previews/ModelViewer'
import PeopleAvatar from '../widgets/PeopleAvatar'
import PictureViewer from '../previews/PictureViewer'
import TaskInfo from '../sides/TaskInfo'
import TaskTypeName from '../widgets/TaskTypeName'
import Spinner from '../widgets/Spinner'
import ValidationTag from '../widgets/ValidationTag'
import VideoPlayer from '../previews/VideoPlayer'

export default {
  name: 'news-page',
  components: {
    DownloadIcon,
    EntityThumbnail,
    ModelViewer,
    PeopleAvatar,
    PictureViewer,
    TaskTypeName,
    ValidationTag,
    Spinner,
    TaskInfo,
    VideoPlayer
  },

  data () {
    return {
      loading: {
        more: false,
        news: false,
        currentTask: true
      },
      errors: {
        news: false
      },
      currentNewsId: null,
      currentPage: 1,
      currentTask: null
    }
  },

  mounted () {
    if (
      (
        this.newsList.length === 0 ||
        (
          this.currentProduction &&
          this.newsList[0].project_id !== this.currentProduction.id
        )
      ) &&
      !this.loading.news
    ) {
      this.init()
    }
  },

  computed: {
    ...mapGetters([
      'currentProduction',
      'newsList',
      'newsListByDay',
      'personMap',
      'taskStatusMap',
      'taskTypeMap'
    ])
  },

  methods: {
    ...mapActions([
      'loadNews',
      'loadSingleNews',
      'loadMoreNews',
      'loadTask'
    ]),

    loadFollowingNews () {
      if (!this.loading.more && !this.loading.news) {
        this.loading.more = true
        this.currentPage += 1
        this.loadMoreNews({
          productionId: this.currentProduction.id,
          page: this.currentPage
        })
          .then(() => {
            this.loading.more = false
          })
      }
    },

    formatDay (date) {
      const utcDate = moment.tz(date, 'UTC')
      return utcDate.format('LL')
    },

    formatTime (date) {
      const utcDate = moment.tz(date, 'UTC')
      return utcDate.format('HH:mm')
    },

    personName (news) {
      const person = this.personMap[news.author_id]
      return person ? person.full_name : ''
    },<commit_msg>Fix time display in news feed<commit_after><template>
<div
  class="columns fixed-page"
>
  <div
    class="column main-column"
  >
    <div
      class="news page"
      ref="body"
      v-scroll="onBodyScroll"
    >
      <div class="timeline-wrapper">
      <div class="timeline">
      <div
        class="empty-list has-text-centered"
        v-if="!loading.news && (!newsList || newsList.length === 0)"
      >
        {{ $t('news.no_news') }}
      </div>
      <div
        class="has-text-centered"
        v-if="loading.news"
      >
        <spinner />
      </div>

      <div
        :key="dayList.length > 0 ? dayList[0].created_at : ''"
        v-for="dayList in newsListByDay"
      >
        <div class="has-text-centered subtitle timeline-entry">
          <span class="big-dot"></span>
          {{ dayList.length > 0 ? formatDay(dayList[0].created_at) : ''}}
        </div>
        <div
          :key="'news-' + news.id"
          v-for="news in dayList"
        >
          <div
            :class="{
              'news-line': true,
              'timeline-entry': true,
              flexrow: true,
              selected: news.id === currentNewsId
            }"
            @click.prevent="onNewsSelected(news)"
          >
            <span :class="{
              dot: true,
              red: hasRetakeValue(news)
            }"></span>
            <span class="date flexrow-item">
              {{ formatTime(news.created_at) }}
            </span>

            <div class="flexrow-item task-type-wrapper">
              <task-type-name
                class="task-type-name"
                :task-type="buildTaskTypeFromNews(news)"
                :production-id="currentProduction.id"
              />
            </div>

            <div class="flexrow-item validation-wrapper">
              <validation-tag
                class="validation-tag"
                :task="buildTaskFromNews(news)"
                v-if="news.change"
              />
            </div>

            <div class="flexrow-item comment-content">
              <div>
                <div class="news-info flexrow">
                  <people-avatar
                    class="flexrow-item"
                    :person="personMap[news.author_id]"
                    :size="30"
                    :no-link="true"
                    v-if="personMap[news.author_id]"
                  />
                  <span
                    class="explaination flexrow-item"
                  >
                    <span class="strong person-name">
                      {{ personName(news) }}
                    </span>
                    <span>
                      {{ $t('news.commented_on') }}
                    </span>
                    <span class="strong">
                      {{ ' ' + news.project_name }} / {{ news.full_entity_name }}
                    </span>
                  </span>
                </div>
              </div>
            </div>
          </div>

          <div class="preview" v-if="news.preview_file_id">
            <div
              :class="{
                'news-line': true,
                'timeline-entry': true,
                flexrow: true,
                selected: news.id === currentNewsId
              }"
              @click.prevent="onNewsSelected(news)"
            >
              <span class="date flexrow-item">
              </span>
              <div class="flexrow-item task-type-wrapper">
              </div>
              <div class="flexrow-item validation-wrapper">
              </div>

              <div class="flexrow-item comment-content">
                <div>
                  <div class="news-info flexrow">
                    <people-avatar
                      class="flexrow-item"
                      :person="personMap[news.author_id]"
                      :size="30"
                      :no-link="true"
                      v-if="personMap[news.author_id]"
                    />
                    <span
                      class="explaination flexrow-item"
                    >
                      <span class="strong person-name">
                        {{ personName(news) }}
                      </span>
                      <span>
                        {{ $t('news.set_preview_on') }}
                      </span>
                      <span class="strong">
                        {{ ' ' + news.project_name }} / {{ news.full_entity_name }}
                      </span>
                    </span>
                  </div>
                </div>
              </div>
            </div>

            <div
              class="has-text-centered"
            >
              <div
                v-if="news.preview_file_extension == 'mp4'"
              >
                <video-player
                  :preview="{id: news.preview_file_id}"
                  :task-type-map="taskTypeMap"
                  :read-only="true"
                  :light="true"
                />
              </div>

              <model-viewer
                class="model-viewer"
                :preview-url="getPreviewPath(news)"
                :preview-dl-path="getPreviewDlPath(news)"
                :light="true"
                :read-only="true"
                v-else-if="news.preview_file_extension == 'obj'"
              />

              <picture-viewer
                :preview="{previews: [{id: news.preview_file_id}]}"
                :light="true"
                :read-only="true"
                ref="preview-picture"
                v-else-if="news.preview_file_extension == 'png'"
              />

              <div
                class="preview-standard-file"
                v-else
              >
                <a
                  class="button"
                  ref="preview-file"
                  :href="getPreviewDlPath(news)"
                >
                  <download-icon class="icon" />
                  <span class="text">
                    {{ $t('tasks.download_pdf_file', {extension: news.preview_file_extension}) }}
                  </span>
                </a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  </div>
  </div>

  <div
    class="column side-column is-hidden-mobile hide-small-screen"
    v-if="currentTask"
  >
    <task-info
      :task="currentTask"
      :is-loading="loading.currentTask"
    />
  </div>
</div>

</template>

<script>
/*
 * This modules aims at displaying what happened on the production during the
 * last few days.
 * News entry are fetched by page of 50. Loading of older news is done via
 * infinite scrolling.
 */
import { mapGetters, mapActions } from 'vuex'
import {
  DownloadIcon
} from 'vue-feather-icons'
import moment from 'moment-timezone'

import EntityThumbnail from '../widgets/EntityThumbnail'
import ModelViewer from '../previews/ModelViewer'
import PeopleAvatar from '../widgets/PeopleAvatar'
import PictureViewer from '../previews/PictureViewer'
import TaskInfo from '../sides/TaskInfo'
import TaskTypeName from '../widgets/TaskTypeName'
import Spinner from '../widgets/Spinner'
import ValidationTag from '../widgets/ValidationTag'
import VideoPlayer from '../previews/VideoPlayer'

export default {
  name: 'news-page',
  components: {
    DownloadIcon,
    EntityThumbnail,
    ModelViewer,
    PeopleAvatar,
    PictureViewer,
    TaskTypeName,
    ValidationTag,
    Spinner,
    TaskInfo,
    VideoPlayer
  },

  data () {
    return {
      loading: {
        more: false,
        news: false,
        currentTask: true
      },
      errors: {
        news: false
      },
      currentNewsId: null,
      currentPage: 1,
      currentTask: null
    }
  },

  mounted () {
    if (
      (
        this.newsList.length === 0 ||
        (
          this.currentProduction &&
          this.newsList[0].project_id !== this.currentProduction.id
        )
      ) &&
      !this.loading.news
    ) {
      this.init()
    }
  },

  computed: {
    ...mapGetters([
      'currentProduction',
      'newsList',
      'newsListByDay',
      'personMap',
      'taskStatusMap',
      'taskTypeMap',
      'user'
    ]),

    timezone () {
      return this.user.timezone || moment.tz.guess()
    }
  },

  methods: {
    ...mapActions([
      'loadNews',
      'loadSingleNews',
      'loadMoreNews',
      'loadTask'
    ]),

    loadFollowingNews () {
      if (!this.loading.more && !this.loading.news) {
        this.loading.more = true
        this.currentPage += 1
        this.loadMoreNews({
          productionId: this.currentProduction.id,
          page: this.currentPage
        })
          .then(() => {
            this.loading.more = false
          })
      }
    },

    formatDay (date) {
      const utcDate = moment.tz(date, 'UTC').tz(this.timezone)
      return utcDate.format('LL')
    },

    formatTime (date) {
      const utcDate = moment.tz(date, 'UTC').tz(this.timezone)
      return utcDate.format('HH:mm')
    },

    personName (news) {
      const person = this.personMap[news.author_id]
      return person ? person.full_name : ''
    },
{'fraction_non_alphanumeric': 0.1297553972723759, 'fraction_numerical': 0.001766882005411076, 'mean_word_length': 1.2589174357695185, 'pattern_counts': {'":': 0, '<': 193, '<?xml version=': 0, '>': 199, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1680141', 'n_tokens_mistral': 5181, 'n_tokens_neox': 4878, 'n_words': 874}