code.gitea.io/gitea@v1.21.7/web_src/js/components/ContextPopup.vue (about)

     1  <script>
     2  import $ from 'jquery';
     3  import {SvgIcon} from '../svg.js';
     4  import {useLightTextOnBackground} from '../utils/color.js';
     5  import tinycolor from 'tinycolor2';
     6  
     7  const {appSubUrl, i18n} = window.config;
     8  
     9  export default {
    10    components: {SvgIcon},
    11    data: () => ({
    12      loading: false,
    13      issue: null,
    14      i18nErrorOccurred: i18n.error_occurred,
    15      i18nErrorMessage: null,
    16    }),
    17    computed: {
    18      createdAt() {
    19        return new Date(this.issue.created_at).toLocaleDateString(undefined, {year: 'numeric', month: 'short', day: 'numeric'});
    20      },
    21  
    22      body() {
    23        const body = this.issue.body.replace(/\n+/g, ' ');
    24        if (body.length > 85) {
    25          return `${body.substring(0, 85)}…`;
    26        }
    27        return body;
    28      },
    29  
    30      icon() {
    31        if (this.issue.pull_request !== null) {
    32          if (this.issue.state === 'open') {
    33            return 'octicon-git-pull-request'; // Open PR
    34          } else if (this.issue.pull_request.merged === true) {
    35            return 'octicon-git-merge'; // Merged PR
    36          }
    37          return 'octicon-git-pull-request'; // Closed PR
    38        } else if (this.issue.state === 'open') {
    39          return 'octicon-issue-opened'; // Open Issue
    40        }
    41        return 'octicon-issue-closed'; // Closed Issue
    42      },
    43  
    44      color() {
    45        if (this.issue.state === 'open') {
    46          return 'green';
    47        } else if (this.issue.pull_request !== null && this.issue.pull_request.merged === true) {
    48          return 'purple';
    49        }
    50        return 'red';
    51      },
    52  
    53      labels() {
    54        return this.issue.labels.map((label) => {
    55          let textColor;
    56          const {r, g, b} = tinycolor(label.color).toRgb();
    57          if (useLightTextOnBackground(r, g, b)) {
    58            textColor = '#eeeeee';
    59          } else {
    60            textColor = '#111111';
    61          }
    62          return {name: label.name, color: `#${label.color}`, textColor};
    63        });
    64      }
    65    },
    66    mounted() {
    67      this.$refs.root.addEventListener('ce-load-context-popup', (e) => {
    68        const data = e.detail;
    69        if (!this.loading && this.issue === null) {
    70          this.load(data);
    71        }
    72      });
    73    },
    74    methods: {
    75      load(data) {
    76        this.loading = true;
    77        this.i18nErrorMessage = null;
    78        $.get(`${appSubUrl}/${data.owner}/${data.repo}/issues/${data.index}/info`).done((issue) => {
    79          this.issue = issue;
    80        }).fail((jqXHR) => {
    81          if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
    82            this.i18nErrorMessage = jqXHR.responseJSON.message;
    83          } else {
    84            this.i18nErrorMessage = i18n.network_error;
    85          }
    86        }).always(() => {
    87          this.loading = false;
    88        });
    89      }
    90    }
    91  };
    92  </script>
    93  <template>
    94    <div ref="root">
    95      <div v-if="loading" class="ui active centered inline loader"/>
    96      <div v-if="!loading && issue !== null">
    97        <p><small>{{ issue.repository.full_name }} on {{ createdAt }}</small></p>
    98        <p><svg-icon :name="icon" :class="['text', color]"/> <strong>{{ issue.title }}</strong> #{{ issue.number }}</p>
    99        <p>{{ body }}</p>
   100        <div>
   101          <div
   102            v-for="label in labels"
   103            :key="label.name"
   104            class="ui label"
   105            :style="{ color: label.textColor, backgroundColor: label.color }"
   106          >
   107            {{ label.name }}
   108          </div>
   109        </div>
   110      </div>
   111      <div v-if="!loading && issue === null">
   112        <p><small>{{ i18nErrorOccurred }}</small></p>
   113        <p>{{ i18nErrorMessage }}</p>
   114      </div>
   115    </div>
   116  </template>