diff --git a/old-sae-airwatch/.storybook/preview-head.html b/old-sae-airwatch/.storybook/preview-head.html new file mode 100644 index 0000000..002b46d --- /dev/null +++ b/old-sae-airwatch/.storybook/preview-head.html @@ -0,0 +1,138 @@ + diff --git a/old-sae-airwatch/.storybook/preview.ts b/old-sae-airwatch/.storybook/preview.ts index c91c628..a2c2301 100644 --- a/old-sae-airwatch/.storybook/preview.ts +++ b/old-sae-airwatch/.storybook/preview.ts @@ -2,7 +2,7 @@ import type {Preview} from '@storybook/angular'; import {moduleMetadata} from '@storybook/angular'; import {Store, StoreModule} from '@ngrx/store'; import {reducers} from '../src/app/reducers'; -// import 'remixicon/fonts/remixicon.css'; +import 'remixicon/fonts/remixicon.css'; const preview: Preview = { parameters: { diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Black.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Black.ttf new file mode 100644 index 0000000..9675b8a Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Black.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-BlackItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-BlackItalic.ttf new file mode 100644 index 0000000..2314595 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-BlackItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Bold.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Bold.ttf new file mode 100644 index 0000000..28f2d3a Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Bold.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-BoldItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-BoldItalic.ttf new file mode 100644 index 0000000..9dc16ad Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-BoldItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraBold.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraBold.ttf new file mode 100644 index 0000000..2290111 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraBold.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraBoldItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraBoldItalic.ttf new file mode 100644 index 0000000..9e30cef Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraBoldItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraLight.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraLight.ttf new file mode 100644 index 0000000..34f0251 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraLight.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraLightItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraLightItalic.ttf new file mode 100644 index 0000000..14f2370 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ExtraLightItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Italic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Italic.ttf new file mode 100644 index 0000000..dc46deb Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Italic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Light.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Light.ttf new file mode 100644 index 0000000..f3c5b70 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Light.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-LightItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-LightItalic.ttf new file mode 100644 index 0000000..bf78286 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-LightItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Medium.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Medium.ttf new file mode 100644 index 0000000..11d4ab2 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Medium.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-MediumItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-MediumItalic.ttf new file mode 100644 index 0000000..62a4fb2 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-MediumItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Regular.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Regular.ttf new file mode 100644 index 0000000..d39c293 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Regular.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-SemiBold.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-SemiBold.ttf new file mode 100644 index 0000000..58a6430 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-SemiBold.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-SemiBoldItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-SemiBoldItalic.ttf new file mode 100644 index 0000000..8cbb7bf Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-SemiBoldItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Thin.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Thin.ttf new file mode 100644 index 0000000..a9d7cb9 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-Thin.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ThinItalic.ttf b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ThinItalic.ttf new file mode 100644 index 0000000..8678b99 Binary files /dev/null and b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/Barlow-ThinItalic.ttf differ diff --git a/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/OFL.txt b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/OFL.txt new file mode 100644 index 0000000..500b734 --- /dev/null +++ b/old-sae-airwatch/.storybook/src/assets/fonts/Barlow/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/old-sae-airwatch/src/app/chatbot/IMPLEMENTATION_SUMMARY.md b/old-sae-airwatch/src/app/chatbot/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..32fb4b2 --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,64 @@ +# Implementation Summary: Stories for Conversation-Item and Export Chat Button + +## Overview + +As requested in the issue, I've created Storybook stories for two key components: +1. The conversation-item component +2. The export chat button component + +## Implementation Details + +### 1. Conversation-Item Component + +I created a standalone Angular component for the conversation-item, which was previously implemented directly in the chatbot.html template. The new component: + +- Encapsulates all the functionality of a conversation item +- Provides proper inputs and outputs for component interaction +- Includes styles from the original implementation +- Supports all states (default, active, pinned) +- Maintains the dropdown menu with hover functionality + +The component is accompanied by a comprehensive set of stories that demonstrate its various states and behaviors. + +### 2. Export Chat Button Component + +I created a standalone Angular component for the export chat button, which was also previously implemented directly in the chatbot.html template. The new component: + +- Encapsulates the export button functionality +- Provides a dropdown menu with export format options (CSV, Excel, TXT) +- Emits events when an export format is selected +- Maintains the same styling as the original implementation +- Supports hover state and dropdown functionality + +The component is accompanied by a set of stories that demonstrate its various states and behaviors. + +## Benefits of This Implementation + +1. **Reusability**: Both components can now be easily reused throughout the application +2. **Maintainability**: Code is more organized and easier to maintain +3. **Testability**: Components can be tested in isolation +4. **Documentation**: Storybook stories serve as living documentation for the components +5. **Consistency**: Ensures consistent behavior and appearance across the application + +## Technical Notes + +- Both components are implemented as standalone Angular components +- They use Bulma CSS classes for styling +- The dropdown functionality works on hover as requested +- The components maintain the same visual appearance as the original implementation + +## Next Steps + +To fully integrate these components into the application: + +1. Replace the inline implementation in chatbot.html with the new components +2. Update any references to the original implementation +3. Run the application to verify everything works as expected + +## Documentation + +A detailed README.md file has been created in the chatbot directory that provides: +- Component features and capabilities +- Available stories and what they demonstrate +- Usage examples +- Instructions for running Storybook diff --git a/old-sae-airwatch/src/app/chatbot/README.md b/old-sae-airwatch/src/app/chatbot/README.md new file mode 100644 index 0000000..0e541ea --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/README.md @@ -0,0 +1,74 @@ +# Chatbot Component Stories + +This document provides information about the Storybook stories created for the chatbot components. + +## Components and Stories + +### 1. ConversationItem Component + +The `ConversationItem` component is a standalone Angular component that displays a conversation item with a dropdown menu for actions. + +#### Component Features: +- Displays conversation name, description, and date +- Shows a pinned icon for pinned conversations +- Provides a dropdown menu with actions (Share, Rename, Pin, Delete) +- Highlights active conversations +- Supports hover state styling + +#### Stories: +- **Default**: Shows a basic conversation item +- **Active**: Demonstrates the active state of a conversation item +- **Pinned**: Shows a pinned conversation with the pin icon +- **LongContent**: Demonstrates how the component handles long names and descriptions + +#### Usage: +```html + + +``` + +### 2. ExportChatButton Component + +The `ExportChatButton` component is a standalone Angular component that displays an "Export chat" button with a dropdown menu for selecting export formats. + +#### Component Features: +- Displays an "Export chat" button with an icon +- Provides a dropdown menu with export format options (CSV, Excel, TXT) +- Supports hover state styling +- Emits events when an export format is selected + +#### Stories: +- **Default**: Shows the basic export button +- **ActiveDropdown**: Demonstrates the button with an open dropdown +- **HoverState**: Shows the hover state styling +- **ExportFunctionality**: Demonstrates the export functionality + +#### Usage: +```html + + +``` + +## Running Storybook + +To run Storybook and view these components: + +1. Ensure you have Node.js v20.19+ or v22.12+ installed +2. Navigate to the project directory +3. Run `npm run storybook` +4. Open your browser to the URL displayed in the terminal (usually http://localhost:6006) + +## Notes + +- The stories are configured to be automatically discovered by Storybook +- Each component has its own set of stories demonstrating different states and behaviors +- The components use Bulma CSS classes for styling +- Both components support hover functionality for dropdowns diff --git a/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.html b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.html new file mode 100644 index 0000000..4246683 --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.html @@ -0,0 +1,65 @@ +
+
+ +
+
+ + + + + + +
+
+ + + {{ conversation.name || 'New Conversation' }} + + + + {{ conversation.lastMessageDate | date: 'dd/MM/yyyy' }} + + + + {{ conversation.description || 'No description' }} + + + +
+ +
+ + + +
+
diff --git a/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.scss b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.scss new file mode 100644 index 0000000..669989f --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.scss @@ -0,0 +1,186 @@ +.conversation-item { + margin-bottom: 16px; + margin-top: 16px; + padding: 16px 16px 18px 32px; + cursor: pointer; + border-radius: 8px; + color: #6D717C; + + .actions { + width: 28px; + height: 28px; + border-radius: 6px; + background: #B9D6ED; + position: relative; + top: 0; + right: 0; + float: right; + + .menu { + cursor: pointer; + text-align: right; + + i { + font-size: 1.2rem; + } + } + + .dropdown { + .dropdown-menu { + right: 0; + left: auto; + } + + .dropdown-item { + i { + margin-right: 0.5rem; + } + } + + &.is-hoverable:hover { + .dropdown-menu { + display: block; + } + } + } + + .trash { + color: red; + fill: red; + } + } + + &:hover { + background: #3B87CC1A; + } + + &.is-active { + background: rgba(#3B87CC1A, 10%); + font-weight: 600; + + .active-peak { + position: relative; + right: calc(-100% - 16px); + top: -35px; + visibility: visible; + } + } + + .pinned-icon { + position: relative; + left: -1.7em; + + i { + color: #FEC553; + fill: #FEC553; + } + } + + .active-peak { + visibility: hidden; + } + + .name { + color: #1E1F22; + font-size: 14px; + font-weight: 600; + display: block; + margin-bottom: 4px; + margin-top: -1.5em; + margin-left: 0; + } + + .description { + color: #6D717C; + font-size: 12px; + font-weight: 400; + line-height: 20px; + margin-right: 4px; + } + + .date { + color: rgba(#5F5F5F99, 60%); + float: right; + text-align: right; + font-family: Barlow; + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: 8px; + margin-top: -1.5em; + } + + input { + display: none; + + &.is-visible { + display: block; + } + } +} + +// Dropdown styles +.dropdown { + position: relative; + display: inline-block; + + &.is-active, + &.is-hoverable:hover { + .dropdown-menu { + display: block; + } + } + + .dropdown-trigger { + display: inline-block; + } + + .dropdown-menu { + display: none; + position: absolute; + z-index: 20; + top: 100%; + right: 0; + min-width: 12rem; + background-color: white; + border-radius: 4px; + box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.02); + padding-bottom: 0.5rem; + padding-top: 0.5rem; + margin-top: 0.25rem; + } + + .dropdown-content { + padding: 0.5rem 0; + } + + .dropdown-item { + color: #4a4a4a; + display: block; + font-size: 0.875rem; + line-height: 1.5; + padding: 0.375rem 1rem; + position: relative; + cursor: pointer; + + &:hover { + background-color: #f5f5f5; + color: #0a0a0a; + } + + &.is-active { + background-color: #3273dc; + color: white; + } + } +} + +// LLM avatar +.llm-avatar { + background: white; + width: 24px; + height: 24px; + border-radius: 8px; + background-size: contain; + margin-right: 10px; +} diff --git a/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.stories.ts b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.stories.ts new file mode 100644 index 0000000..b01e4c4 --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.stories.ts @@ -0,0 +1,75 @@ +import type { Meta, StoryObj } from '@storybook/angular'; +import { ConversationItem } from './conversation-item'; +import { moduleMetadata } from '@storybook/angular'; +import { NgClass, NgIf, DatePipe } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { ChatbotConversation } from '../../services/conversations.service'; + +// More on how to set up stories at: https://storybook.js.org/docs/angular/writing-stories/introduction +const meta: Meta = { + title: 'Chatbot/ConversationItem', + component: ConversationItem, + tags: ['autodocs'], + decorators: [ + moduleMetadata({ + imports: [NgClass, NgIf, DatePipe, FormsModule], + providers: [] + }) + ], + argTypes: { + isActive: { control: 'boolean' }, + onSelect: { action: 'selected' }, + onShare: { action: 'shared' }, + onRename: { action: 'renamed' }, + onPin: { action: 'pinned' }, + onDelete: { action: 'deleted' } + }, +}; + +export default meta; +type Story = StoryObj; + +// Create a mock conversation +const createMockConversation = (name: string, description: string, pinned: boolean = false): ChatbotConversation => { + const conversation = new ChatbotConversation(); + conversation.name = name; + conversation.description = description; + conversation.pinned = pinned; + conversation.lastMessageDate = new Date(); + return conversation; +}; + +// Default story +export const Default: Story = { + args: { + conversation: createMockConversation('Project Discussion', 'Latest updates on the project timeline'), + isActive: false + }, +}; + +// Active conversation +export const Active: Story = { + args: { + conversation: createMockConversation('Project Discussion', 'Latest updates on the project timeline'), + isActive: true + }, +}; + +// Pinned conversation +export const Pinned: Story = { + args: { + conversation: createMockConversation('Important Meeting', 'CEO quarterly update', true), + isActive: false + }, +}; + +// Long name and description +export const LongContent: Story = { + args: { + conversation: createMockConversation( + 'Very Long Conversation Name That Should Truncate', + 'This is a very long description that should demonstrate how the component handles overflow text in the description area of the conversation item component', + ), + isActive: false + }, +}; diff --git a/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.ts b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.ts new file mode 100644 index 0000000..7feff6e --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/conversation-item/conversation-item.ts @@ -0,0 +1,52 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; +import { NgClass, NgIf, DatePipe } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { ChatbotConversation } from '../../services/conversations.service'; + +@Component({ + selector: 'app-conversation-item', + standalone: true, + imports: [NgClass, NgIf, DatePipe, FormsModule], + templateUrl: './conversation-item.html', + styleUrl: './conversation-item.scss' +}) +export class ConversationItem { + @Input() conversation: ChatbotConversation = new ChatbotConversation(); + @Input() isActive: boolean = false; + + @Output() onSelect = new EventEmitter(); + @Output() onShare = new EventEmitter(); + @Output() onRename = new EventEmitter(); + @Output() onPin = new EventEmitter(); + @Output() onDelete = new EventEmitter(); + + isDropdownActive: boolean = false; + + toggleDropdown() { + this.isDropdownActive = !this.isDropdownActive; + } + + selectConversation() { + this.onSelect.emit(this.conversation); + } + + shareConversation(event: Event) { + event.stopPropagation(); + this.onShare.emit(this.conversation); + } + + renameConversation(event: Event) { + event.stopPropagation(); + this.onRename.emit(this.conversation); + } + + pinConversation(event: Event) { + event.stopPropagation(); + this.onPin.emit(this.conversation); + } + + deleteConversation(event: Event) { + event.stopPropagation(); + this.onDelete.emit(this.conversation); + } +} diff --git a/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.html b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.html new file mode 100644 index 0000000..7131562 --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.html @@ -0,0 +1,23 @@ + diff --git a/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.scss b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.scss new file mode 100644 index 0000000..526b14c --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.scss @@ -0,0 +1,85 @@ +.export-chat-button { + position: relative; + right: 0; + display: inline-flex; + height: 44px; + padding: 0 20px; + justify-content: center; + align-items: center; + gap: 10px; + flex-shrink: 0; + border-radius: 8px; + border: 1px solid #005AA2; + color: #005AA2; + text-align: center; + font-size: 20px; + font-style: normal; + font-weight: 500; + line-height: 100px; /* 500% */ + + &:hover { + background: #005AA2; + color: white; + } + + .label { + font-size: 14px; + line-height: normal; + } +} + +// Dropdown styles +.dropdown { + position: relative; + display: inline-block; + + &.is-active, + &.is-hoverable:hover { + .dropdown-menu { + display: block; + } + } + + .dropdown-trigger { + display: inline-block; + } + + .dropdown-menu { + display: none; + position: absolute; + z-index: 20; + top: 100%; + right: 0; + min-width: 12rem; + background-color: white; + border-radius: 4px; + box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.02); + padding-bottom: 0.5rem; + padding-top: 0.5rem; + margin-top: 0.25rem; + } + + .dropdown-content { + padding: 0.5rem 0; + } + + .dropdown-item { + color: #4a4a4a; + display: block; + font-size: 0.875rem; + line-height: 1.5; + padding: 0.375rem 1rem; + position: relative; + cursor: pointer; + + &:hover { + background-color: #f5f5f5; + color: #0a0a0a; + } + + &.is-active { + background-color: #3273dc; + color: white; + } + } +} diff --git a/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.stories.ts b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.stories.ts new file mode 100644 index 0000000..5d12930 --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.stories.ts @@ -0,0 +1,61 @@ +import type { Meta, StoryObj } from '@storybook/angular'; +import { ExportChatButton } from './export-chat-button'; +import { moduleMetadata } from '@storybook/angular'; +import { NgClass } from '@angular/common'; + +// More on how to set up stories at: https://storybook.js.org/docs/angular/writing-stories/introduction +const meta: Meta = { + title: 'Chatbot/ExportChatButton', + component: ExportChatButton, + tags: ['autodocs'], + decorators: [ + moduleMetadata({ + imports: [NgClass], + providers: [] + }) + ], + argTypes: { + onExport: { action: 'exported' } + }, +}; + +export default meta; +type Story = StoryObj; + +// Default state +export const Default: Story = { + args: {}, +}; + +// Active dropdown +export const ActiveDropdown: Story = { + args: {}, + play: async ({ canvasElement, component }) => { + // Simulate clicking the button to open the dropdown + component.isDropdownActive = true; + }, +}; + +// Custom story to demonstrate hover state +export const HoverState: Story = { + args: {}, + parameters: { + docs: { + description: { + story: 'Hover over the button to see the hover state. The button background changes to blue and text becomes white.' + } + } + } +}; + +// Custom story to demonstrate the export functionality +export const ExportFunctionality: Story = { + args: {}, + parameters: { + docs: { + description: { + story: 'Click on the button to open the dropdown, then select a format to export. The onExport event will be emitted with the selected format.' + } + } + } +}; diff --git a/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.ts b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.ts new file mode 100644 index 0000000..e63b0c5 --- /dev/null +++ b/old-sae-airwatch/src/app/chatbot/export-chat-button/export-chat-button.ts @@ -0,0 +1,27 @@ +import { Component, Output, EventEmitter } from '@angular/core'; +import { NgClass } from '@angular/common'; + +export type ExportFormat = 'csv' | 'excel' | 'txt'; + +@Component({ + selector: 'app-export-chat-button', + standalone: true, + imports: [NgClass], + templateUrl: './export-chat-button.html', + styleUrl: './export-chat-button.scss' +}) +export class ExportChatButton { + @Output() onExport = new EventEmitter(); + + isDropdownActive: boolean = false; + + toggleDropdown() { + this.isDropdownActive = !this.isDropdownActive; + } + + exportAs(format: ExportFormat, event: Event) { + event.stopPropagation(); + this.onExport.emit(format); + this.isDropdownActive = false; + } +} diff --git a/old-sae-airwatch/src/app/services/conversations.service.ts b/old-sae-airwatch/src/app/services/conversations.service.ts index 45c0f10..a54f328 100644 --- a/old-sae-airwatch/src/app/services/conversations.service.ts +++ b/old-sae-airwatch/src/app/services/conversations.service.ts @@ -25,7 +25,7 @@ export class ChatbotConversation { public visibleInput: boolean = false; public pinned: boolean = false; public description: string = "Some 15 billion years ago the universe emerged from a hot, dense sea of..."; - public lastMessageDate: string = new Date().toLocaleDateString(); + public lastMessageDate: any = new Date().toLocaleDateString(); public sources: Array = []; public filters: Array = [];