npm.io
0.1.8 • Published 8h ago

@dcodegroup-au/vue-activity-log

Licence
MIT
Version
0.1.8
Deps
0
Size
209 kB
Vulns
0
Weekly
0

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

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="user@example.com"
    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": "user@example.com",
        "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

Keywords