• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Freegle / iznik-nuxt3 / c1db7197-804e-45b4-8d43-ff5992ab766b

30 Mar 2026 09:10PM UTC coverage: 44.828% (+1.4%) from 43.397%
c1db7197-804e-45b4-8d43-ff5992ab766b

push

circleci

CircleCI Auto-merge
Auto-merge master to production after successful tests - Original commit: fix: saveEmail takes raw string, not object

4385 of 10026 branches covered (43.74%)

Branch coverage included in aggregate %.

0 of 2 new or added lines in 2 files covered. (0.0%)

454 existing lines in 28 files now uncovered.

1981 of 4175 relevant lines covered (47.45%)

59.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/components/ChatMessageModMail.vue
1
<template>
2
  <div>
3
    <b-row>
4
      <b-col>
5
        <div class="media">
6
          <b-card border-variant="success" :class="{ 'ms-auto': !amUser }">
7
            <b-card-title>
8
              <div v-if="group">
×
9
                <h4>
10
                  <ProfileImage
11
                    v-if="group"
×
12
                    :image="group.profile"
13
                    class="me-1 mb-1 mt-1 inline"
14
                    is-thumbnail
15
                    size="sm"
16
                  />
17
                  <span class="align-middle">
18
                    Message from {{ group.namedisplay }} Volunteers
19
                  </span>
20
                </h4>
21
              </div>
22
              <h4 v-else>Message from Freegle Volunteers</h4>
23
              <div v-if="realMod" class="text-muted small">
×
24
                <div class="small">
25
                  (Sent by
26
                  <v-icon icon="hashtag" class="text-muted" scale="0.5" />{{
27
                    chatmessage.userid
28
                  }})
29
                </div>
30
              </div>
31
            </b-card-title>
32
            <b-card-text>
33
              <div :class="emessage ? 'media-body chatMessage' : 'media-body'">
×
34
                <span>
35
                  <span
36
                    v-if="
×
37
                      chatmessage.secondsago < 60 ||
38
                      chatmessage.id > chat.lastmsgseen
39
                    "
40
                    class="prewrap fw-bold"
41
                    >{{ emessage }}</span
42
                  >
43
                  <span v-else class="preline forcebreak">{{ emessage }}</span>
44
                  <b-img
45
                    v-if="chatmessage.image"
×
46
                    fluid
47
                    :src="chatmessage.image.path"
48
                    lazy
49
                    rounded
50
                  />
51
                </span>
52
              </div>
53
              <div v-if="chatmessage.refmsgid && refmsg && !miscStore.modtools">
×
54
                <hr />
55
                <p>
×
56
                  If you have been asked to edit and resend this message, you
57
                  can do so here:
58
                </p>
59
                <b-button variant="warning" @click="repost">
60
                  <v-icon icon="pen" /> Edit and Resend
×
61
                </b-button>
62
              </div>
63
              <NoticeMessage
64
                v-else-if="chat.chattype === 'User2User'"
65
                variant="warning"
66
                class="mt-2"
67
              >
68
                <p>
×
69
                  Volunteers won't see any replies you make in here about this
70
                  message - they'll go to the other freegler. If you want to
71
                  contact the volunteers, please use the button below.
72
                </p>
73
                <GroupSelect
74
                  v-model="contactGroupId"
75
                  remember="contactmods"
76
                  class="mb-3"
77
                />
78
                <ChatButton
79
                  :groupid="contactGroupId"
80
                  size="md"
81
                  title="Contact community volunteers"
82
                  variant="primary"
83
                  class="mb-2"
84
                />
85
              </NoticeMessage>
86
            </b-card-text>
87
          </b-card>
88
        </div>
89
      </b-col>
90
    </b-row>
91
  </div>
92
</template>
93
<script setup>
94
import { ref, computed } from 'vue'
95
import NoticeMessage from './NoticeMessage'
96
import ChatButton from './ChatButton'
97
import { useComposeStore } from '~/stores/compose'
98
import { useMiscStore } from '~/stores/misc'
99
import {
100
  fetchReferencedMessage,
101
  useChatMessageBase,
102
} from '~/composables/useChat'
103
import ProfileImage from '~/components/ProfileImage'
104
import GroupSelect from '~/components/GroupSelect'
105
import { useRouter } from '#imports'
106

UNCOV
107
const props = defineProps({
×
108
  chatid: {
109
    type: Number,
110
    required: true,
111
  },
112
  id: {
113
    type: Number,
114
    required: true,
115
  },
116
  last: {
117
    type: Boolean,
118
    required: false,
119
    default: false,
120
  },
121
  pov: {
122
    type: Number,
123
    required: false,
124
    default: null,
125
  },
126
  highlightEmails: {
127
    type: Boolean,
128
    required: false,
129
    default: false,
130
  },
131
})
132

133
// Use the chat base composable
134
const { chat, chatmessage, emessage, refmsg, me, myid, realMe } =
135
  useChatMessageBase(props.chatid, props.id, props.pov)
136

137
const composeStore = useComposeStore()
138
const miscStore = useMiscStore()
139
const contactGroupId = ref(null)
140

141
// Setup
142
await fetchReferencedMessage(props.chatid, props.id)
×
143

UNCOV
144
const group = computed(() => {
×
145
  return chat.value && chat.value.group ? chat.value.group : null
×
146
})
147

148
const amUser = computed(() => {
149
  return chat.value && chat.value.user && chat.value.user.id === myid
×
150
})
151

152
const realMod = computed(() => {
153
  // Show "(Sent by #...)" to moderators, support, and admins
154
  return (
155
    realMe.value &&
×
156
    (realMe.value.systemrole === 'Moderator' ||
157
      realMe.value.systemrole === 'Support' ||
158
      realMe.value.systemrole === 'Admin')
159
  )
160
})
161

UNCOV
162
async function repost() {
×
163
  const message = Object.assign({}, refmsg.value)
×
164

UNCOV
165
  if (message) {
×
166
    // Remove any partially composed messages we currently have, because they'll be confusing.
167
    await composeStore.clearMessages()
168

169
    // Add this message to the compose store so that it will show up on the compose page.
170
    await composeStore.setMessage(
171
      0,
172
      {
173
        type: message.type,
174
        item: message.item?.name?.trim(),
×
175
        description: message.textbody.trim(),
176
        availablenow: message.availablenow,
177
        repostof: chatmessage.value.refmsgid,
178
      },
179
      me.value
180
    )
181

182
    composeStore.setAttachmentsForMessage(0, message.attachments)
183

184
    const router = useRouter()
185
    router.push(message.type === 'Offer' ? '/give' : '/find')
×
186
  }
187
}
188
</script>
189
<style scoped lang="scss">
190
.chatMessage {
191
  border: 1px solid $color-gray--light;
192
  border-radius: var(--radius-lg, 0.75rem);
193
  padding-top: 2px;
194
  padding-bottom: 2px;
195
  padding-left: 4px;
196
  padding-right: 2px;
197
  word-wrap: break-word;
198
  line-height: 1.5;
199
}
200
</style>
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc