npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dcodegroup-au/vue-activity-log

v0.1.6

Published

A Vue 3 component for displaying activity logs with timeline, comments, and notifications.

Readme

Vue Activity Log Components

A collection of Vue 3 components for displaying activity logs, comments, and communications. Includes timeline view, table list view, and modal dialogs for email previews and delete confirmations.

Installation

npm install @dcodegroup-au/vue-activity-log

Setup

1. Register components globally (recommended)

import { createApp } from 'vue'
import App from './App.vue'
import VueActivityLogPlugin from '@dcodegroup-au/vue-activity-log'
import '@dcodegroup-au/vue-activity-log/dist/style.css'

const app = createApp(App)
app.use(VueActivityLogPlugin)
app.mount('#app')

2. Register components locally

<script setup>
import { VActivityLog, ActivityEmail, ActivityLogDeleteComment, ActivityLogList } from '@dcodegroup-au/vue-activity-log'
import '@dcodegroup-au/vue-activity-log/dist/style.css'
</script>

3. Setup dependencies

Make sure your project has these peer dependencies installed:

npm install vue@^3.0.0 axios vue-i18n @heroicons/vue @dcodegroup/vue-mention mitt vue-markdown-render

4. Setup event bus (optional, but required for modals)

If using modals, provide a bus (mitt event emitter) via provide:

import mitt from 'mitt'
import { createApp } from 'vue'

const bus = mitt()
const app = createApp(...)
app.provide('bus', bus)
app.mount('#app')

Or in your root component:

<script setup>
import mitt from 'mitt'

const bus = mitt()
</script>

<template>
  <div>
    <provide key="bus" :value="bus">
      <YourComponent />
    </provide>
  </div>
</template>

Components

1. VActivityLog (Timeline View)

Main activity log component displaying activities in a vertical timeline format with comments support.

Basic Usage

<template>
  <VActivityLog
    model-class="Post"
    model-id="123"
    get-url="/api/activity-logs"
    comment-url="/api/activity-logs/comments"
    load-users-url="/api/activity-logs/filters/facets/created_by"
    :current-user="{ id: 1, full_name: 'John Doe' }"
  />
</template>

<script setup>
import { VActivityLog } from '@dcodegroup-au/vue-activity-log'
</script>

Props

{
  // URLs
  getUrl: String,                    // Default: "/activity-logs"
  commentUrl: String,                // Default: "/activity-logs/comments"
  loadUsersUrl: String,              // Default: "/activity-logs/filters/facets/created_by"
  resendUrl: String,                 // Default: "/activity-logs/resent-communication"
  
  // Model identification (required)
  modelClass: String,                // e.g., "Post", "User" (required)
  modelId: String,                   // e.g., "123" (required)
  
  // User info
  currentUser: Object,               // { id, full_name, ... }
  
  // Display options
  allowComment: Boolean,             // Default: false
  allowResend: Boolean,              // Default: false
  isWidgetView: Boolean,             // Default: false (compact view)
  defaultCollapView: Boolean,        // Default: false
  
  // Comment options
  canMentionInComment: Boolean,      // Default: true
  canMentionSpace: Boolean,          // Default: true
  enterToComment: Boolean,           // Default: false (Ctrl+Enter to submit)
  autoGrowInput: Boolean,            // Default: false (auto-expand textarea)
  
  // Content options
  isMarkdownContent: Boolean,        // Default: false
  showFullComment: Boolean,          // Default: false
  noActivityText: String,            // Default: "No activity found"
  
  // Timezone
  timezone: String,                  // e.g., "UTC", "Asia/Bangkok"
  
  // Additional models
  extra_models: String,              // For filtering by related models
  
  // Events/Callbacks
  filterEvent: String,               // Default: "activityLogFilterChange"
  resendEvent: String,               // Default: "activityLogResend"
  modalEvent: String,                // Default: "openActivityLogModal"
  activityEmailComponentName: String,// Default: "ActivityEmail"
  
  // Behavior
  refreshSelf: Boolean,              // Default: false (refresh on comment)
}

Events

<template>
  <VActivityLog
    @comment-added="handleCommentAdded"
  />
</template>

<script setup>
const handleCommentAdded = (data) => {
  console.log(data)
  // {
  //   event,
  //   activities,
  //   modelId,
  //   modelClass
  // }
}
</script>

Slots

<template>
  <VActivityLog model-class="Post" model-id="123">
    <!-- Custom action slot in search bar -->
    <button>Export</button>
  </VActivityLog>
</template>

Full Example with Comments

<template>
  <div class="p-4">
    <VActivityLog
      model-class="Post"
      model-id="123"
      get-url="/api/activity-logs"
      comment-url="/api/activity-logs/comments"
      load-users-url="/api/activity-logs/filters/facets/created_by"
      :current-user="currentUser"
      :allow-comment="true"
      :allow-resend="true"
      :can-mention-in-comment="true"
      :enter-to-comment="false"
      :auto-grow-input="true"
      :timezone="timezone"
      @comment-added="onCommentAdded"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { VActivityLog } from '@dcodegroup-au/vue-activity-log'

const currentUser = ref({
  id: 1,
  full_name: 'John Doe'
})

const timezone = ref('Asia/Bangkok')

const onCommentAdded = (data) => {
  console.log('Comment added:', data)
}
</script>

2. ActivityLogList (Table View)

Displays activities in a table format with search and filtering.

Basic Usage

<template>
  <ActivityLogList
    model-class="Post"
    model-id="123"
    get-url="/api/activity-logs"
    modal-event="openActivityLogModal"
  />
</template>

<script setup>
import { ActivityLogList } from '@dcodegroup-au/vue-activity-log'
</script>

Props

{
  // URLs
  getUrl: String,              // Default: "/activity-logs"
  
  // Model identification (required)
  modelClass: String,          // (required)
  modelId: String | Number,    // (required)
  
  // Display options
  allowComment: Boolean,       // Default: false
  refreshSelf: Boolean,        // Default: false
  
  // User
  currentUser: String,         // Default: "Guest"
  
  // Events
  modalEvent: String,          // Default: "openActivityLogModal"
  filterEvent: String,         // Default: "activityLogFilterChange"
}

Full Example

<template>
  <div class="p-4">
    <ActivityLogList
      model-class="Post"
      model-id="123"
      get-url="/api/activity-logs"
      current-user="John Doe"
      :allow-comment="false"
    />
  </div>
</template>

<script setup>
import { ActivityLogList } from '@your-org/vue-activity-log'
</script>

3. ActivityEmail (Modal Content)

Component for previewing email communications.

Basic Usage

<template>
  <ActivityEmail
    to="[email protected]"
    subject="Welcome to our platform"
    content="<p>Hello,</p><p>Welcome!</p>"
    date="2024-06-16 10:30 AM"
    :is-markdown-content="false"
  />
</template>

<script setup>
import { ActivityEmail } from '@dcodegroup-au/vue-activity-log'
</script>

Props

{
  to: String,                      // (required)
  subject: String,                 // (required)
  content: String,                 // (required) - HTML or Markdown
  date: String,                    // Optional
  isMarkdownContent: Boolean,      // Default: false
}

Used with ActivityLogModal

<template>
  <ActivityLogModal />
</template>

<script setup>
import { ref } from 'vue'
import { ActivityLogModal } from '@your-org/vue-activity-log'
import mitt from 'mitt'

const bus = mitt()

// Somewhere in your code, emit to open modal:
const openEmailPreview = (communication) => {
  bus.emit('openActivityLogModal', {
    componentName: 'ActivityEmail',
    componentData: {
      to: communication.to,
      subject: communication.subject,
      content: communication.content,
      date: communication.date,
      isMarkdownContent: true
    }
  })
}
</script>

4. ActivityLogDeleteComment (Modal Content)

Component for confirming comment deletion.

Props

{
  endpoint: String,  // (required) - DELETE endpoint for the comment
}

Events

Emits on bus:

  • refreshActivityLog - to refresh activity list
  • closeActivityLogModal - to close modal

Used with ActivityLogModal

<template>
  <ActivityLogModal />
</template>

<script setup>
import { ref } from 'vue'
import { ActivityLogModal } from '@your-org/vue-activity-log'
import mitt from 'mitt'

const bus = mitt()

// Somewhere in your code, emit to open delete modal:
const openDeleteModal = (comment) => {
  bus.emit('openActivityLogModal', {
    componentName: 'ActivityLogDeleteComment',
    componentData: {
      endpoint: `/api/activity-logs/comments/${comment.id}`
    }
  })
}
</script>

Complete App Example

<template>
  <div class="app">
    <header>
      <h1>Activity Log Demo</h1>
    </header>
    
    <main>
      <div class="tabs">
        <button 
          @click="activeTab = 'timeline'"
          :class="{ active: activeTab === 'timeline' }"
        >
          Timeline View
        </button>
        <button 
          @click="activeTab = 'list'"
          :class="{ active: activeTab === 'list' }"
        >
          List View
        </button>
      </div>

      <!-- Timeline View -->
      <div v-if="activeTab === 'timeline'" class="tab-content">
        <VActivityLog
          model-class="Post"
          model-id="123"
          get-url="/api/activity-logs"
          comment-url="/api/activity-logs/comments"
          load-users-url="/api/activity-logs/filters/facets/created_by"
          resend-url="/api/activity-logs/resent-communication"
          :current-user="currentUser"
          :allow-comment="true"
          :allow-resend="true"
          :can-mention-in-comment="true"
          :auto-grow-input="true"
          :timezone="timezone"
          @comment-added="onCommentAdded"
        />
      </div>

      <!-- List View -->
      <div v-if="activeTab === 'list'" class="tab-content">
        <ActivityLogList
          model-class="Post"
          model-id="123"
          get-url="/api/activity-logs"
          :current-user="currentUser.full_name"
        />
      </div>
    </main>

    <!-- Modal for previews -->
    <ActivityLogModal />
  </div>
</template>

<script setup>
import { ref, provide } from 'vue'
import mitt from 'mitt'
import { 
  VActivityLog, 
  ActivityLogList, 
  ActivityLogModal 
} from '@dcodegroup-au/vue-activity-log'
import '@dcodegroup-au/vue-activity-log/dist/style.css'

// Setup event bus
const bus = mitt()
provide('bus', bus)

// State
const activeTab = ref('timeline')
const currentUser = ref({
  id: 1,
  full_name: 'John Doe'
})
const timezone = ref('Asia/Bangkok')

// Handlers
const onCommentAdded = (data) => {
  console.log('Comment added on:', data.modelClass, data.modelId)
}
</script>

<style scoped>
.app {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.tabs button {
  padding: 10px 20px;
  border: 1px solid #ccc;
  background: #f5f5f5;
  cursor: pointer;
  border-radius: 4px;
}

.tabs button.active {
  background: #007bff;
  color: white;
  border-color: #007bff;
}

.tab-content {
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 20px;
}
</style>

API Requirements

Your backend should provide these endpoints:

GET /activity-logs

// Query params:
// modelClass: string
// modelId: string
// timezone: string (optional)
// filter[term]: string (search)
// filter[created_by]: string (user filter)

// Response:
{
  "data": [
    {
      "id": 1,
      "user": "John Doe",
      "title": "Created post",
      "description": "Post description",
      "type": "Create", // or "Update", "Delete", "Comment", "Phone Call"
      "color": "blue",
      "icon": "PlusIcon",
      "created_at_date": "2024-06-16 10:30 AM",
      "is_edited": false,
      "communication": {
        "type": "Email", // or "Sms"
        "to": "[email protected]",
        "subject": "Subject",
        "content": "<p>Content</p>",
        "date": "2024-06-16",
        "reads_count": 2,
        "read_at_date": "2024-06-17"
      },
      "meta": { "action": "Created" },
      "delete_comment_endpoint": "/api/activity-logs/comments/1"
    }
  ]
}

POST /activity-logs/comments

// Request body:
{
  "modelClass": "Post",
  "modelId": "123",
  "comment": "User's comment",
  "currentUrl": "http://...",
  "currentUser": "John Doe",
  "timezone": "Asia/Bangkok"
}

// Response: { "data": [...activities] }

PATCH /activity-logs/comments/:id

// Same as POST but updates existing comment

DELETE /activity-logs/comments/:id

// Response: { "data": [...activities] }

POST /activity-logs/resent-communication/:id

// Response: success

GET /activity-logs/filters/facets/created_by

// Query params:
// s: string (search text)
// modelClass: string
// modelId: string

// Response:
{
  "data": [
    { "label": "John Doe", "value": 1 },
    { "label": "Jane Smith", "value": 2 }
  ]
}

Styling

Components use Tailwind CSS classes. Make sure Tailwind is configured in your project. The package exports minimal CSS (mostly for animations and component-specific styles).

License

MIT