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

Freegle / iznik-nuxt3 / 9bce52b0-957c-43ee-92e4-3867075656a0

04 Dec 2025 02:52PM UTC coverage: 42.676% (-1.8%) from 44.461%
9bce52b0-957c-43ee-92e4-3867075656a0

push

circleci

edwh
Modernize chat buttons, fix sidebars and footer layout

- ChatFooter: Modernize desktop action buttons to chip-style design
- MessageExpanded: Force ratings to hide on mobile with !important
- MyMessageReply: Hide ratings section on xxs screens (≤320px)
- SidebarRight: Full width and height for job ads, match left sidebar
- SidebarLeft: Remove margin from footer wrapper
- BotLeftBox: Rework footer with text links left, social icons right

2986 of 7770 branches covered (38.43%)

Branch coverage included in aggregate %.

3459 of 7332 relevant lines covered (47.18%)

13.59 hits per line

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

0.0
/components/ChatMessageText.vue
1
<template>
2
  <div
3
    class="chatMessageWrapper"
4
    :class="{ myChatMessage: messageIsFromCurrentUser }"
5
  >
6
    <div class="chatMessageProfilePic">
7
      <ProfileImage
8
        :image="chatMessageProfileImage"
9
        :name="chatMessageProfileName"
×
10
        class="inline"
11
        is-thumbnail
12
        size="sm"
×
13
      />
14
    </div>
×
15
    <div class="chatMessage forcebreak chatMessage__owner">
16
      <div>
17
        <span v-if="!highlightEmails">
×
18
          <span v-if="messageIsNew" class="prewrap font-weight-bold">{{
19
            emessage
20
          }}</span>
21
          <span v-else class="preline forcebreak">{{ emessage }}</span>
×
22
          <b-img
23
            v-if="chatmessage?.image"
24
            fluid
25
            :src="chatmessage?.image.path"
26
            lazy
27
            rounded
×
28
          />
29
        </span>
30
        <span v-else>
31
          <span v-if="messageIsNew" class="font-weight-bold">
32
            <Highlighter
33
              :text-to-highlight="emessage"
34
              :search-words="[regexEmail]"
35
              highlight-class-name="highlight"
36
              class="prewrap"
37
            />
38
          </span>
39
          <span v-else>
40
            <Highlighter
41
              :text-to-highlight="emessage"
×
42
              :search-words="[regexEmail]"
43
              highlight-class-name="highlight"
44
              class="preline forcebreak"
45
            />
46
          </span>
×
47
          <b-img
48
            v-if="chatmessage?.image"
49
            fluid
50
            :src="chatmessage?.image.path"
51
            lazy
52
            rounded
×
53
          />
54
        </span>
55
      </div>
56
      <div v-if="lat || lng">
57
        <l-map
58
          ref="map"
59
          :zoom="16"
60
          :max-zoom="maxZoom"
61
          :center="[lat, lng]"
62
          :style="'width: 100%; height: 200px'"
63
        >
64
          <l-tile-layer :url="osmtile()" :attribution="attribution()" />
65
          <l-marker :lat-lng="[lat, lng]" :interactive="false" />
66
        </l-map>
67
        <div class="small text-muted">
68
          (Map shows approximate location of {{ postcode }})
69
        </div>
70
      </div>
71
    </div>
72
  </div>
73
</template>
74
<script setup>
75
import Highlighter from 'vue-highlight-words'
76
import { useChatMessageBase } from '~/composables/useChat'
77
import { ref, computed, onMounted } from '#imports'
78
import ProfileImage from '~/components/ProfileImage'
79
import { MAX_MAP_ZOOM, POSTCODE_REGEX } from '~/constants'
80
import { attribution, osmtile } from '~/composables/useMap'
81
import { useLocationStore } from '~/stores/location'
82

83
const props = defineProps({
84
  chatid: {
85
    type: Number,
86
    required: true,
87
  },
88
  id: {
×
89
    type: Number,
90
    required: true,
91
  },
92
  pov: {
93
    type: Number,
94
    required: false,
95
    default: null,
96
  },
97
  highlightEmails: {
98
    type: Boolean,
99
    required: false,
100
    default: false,
101
  },
102
})
103

104
// Use properties from ChatBase component via composable
105
const {
106
  chat,
107
  chatmessage,
108
  emessage,
109
  messageIsFromCurrentUser,
110
  chatMessageProfileImage,
×
111
  chatMessageProfileName,
112
  regexEmail,
113
} = useChatMessageBase(props.chatid, props.id, props.pov)
114

115
// Data properties
116
const lat = ref(null)
117
const lng = ref(null)
118

119
// Computed properties
120
const maxZoom = computed(() => MAX_MAP_ZOOM)
×
121

×
122
const messageIsNew = computed(() => {
×
123
  return (
×
124
    chatmessage.value?.secondsago < 60 ||
125
    chatmessage.value?.id > chat.value?.lastmsgseen
126
  )
×
127
})
×
128

129
const postcode = computed(() => {
×
130
  let ret = null
×
131

×
132
  const postcodeMatch = chatmessage.value?.message.match(POSTCODE_REGEX)
133

134
  if (postcodeMatch?.length) {
135
    if (!postcodeMatch[0].includes(' ')) {
136
      // Make sure we have a space in the right place, because this helps with autocomplete
137
      ret = postcodeMatch[0].replace(/^(.*)(\d)/, '$1 $2')
×
138
    } else {
×
139
      ret = postcodeMatch[0]
×
140
    }
×
141
  }
×
142

×
143
  return ret
×
144
})
×
145

×
146
// Lifecycle hooks
×
147
onMounted(async () => {
148
  if (postcode.value) {
×
149
    // Use typeahead to find the postcode location.
150
    const locationStore = useLocationStore()
151
    const locs = await locationStore.typeahead(postcode.value)
×
152

153
    if (locs?.length) {
×
154
      lat.value = locs[0].lat
×
155
      lng.value = locs[0].lng
×
156
    }
×
157
  }
158
})
159
</script>
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