Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(feedback-container): adding feedback-container component #34

Closed
wants to merge 11 commits into from
67 changes: 67 additions & 0 deletions packages/feedback/__stories__/feedback-container.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* @license
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these components all be put in the Chat package instead?

*
* Copyright IBM Corp. 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import '../components/feedback-container/feedback-container';
import '../components/input-container/input-container';
import '../components/output-container/output-container';

import { html } from 'lit';

let hello = 'sajnsjankjnsa';

Check failure on line 16 in packages/feedback/__stories__/feedback-container.stories.js

View workflow job for this annotation

GitHub Actions / lint

'hello' is assigned a value but never used. Allowed unused vars must match /^_/u
let isVisible = false;

Check failure on line 17 in packages/feedback/__stories__/feedback-container.stories.js

View workflow job for this annotation

GitHub Actions / lint

'isVisible' is assigned a value but never used. Allowed unused vars must match /^_/u
setTimeout(() => {
isVisible = true;
}, 3000);
/**
* More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction
*/
export default {
title: 'Components/Feedback container/Feedback container',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we put these components in the chat package, we probably want to change the storybook title here to
Components/Chat/Feedback container so that they are all listed under the Chat component in storybook

tags: ['autodocs'],
};

/**
* More on writing stories with args: https://storybook.js.org/docs/web-components/writing-stories/args
*
* @type {{args: {label: string}, render: (function(*): TemplateResult<1>)}}
*/
export const Default = {
args: {
label: 'Feedback container',
},

/**
* Renders the template for Storybook
* @param {object} args Storybook arguments
* @returns {TemplateResult<1>}
*/
render: (args) =>

Check failure on line 44 in packages/feedback/__stories__/feedback-container.stories.js

View workflow job for this annotation

GitHub Actions / lint

'args' is defined but never used. Allowed unused args must match /^_/u
html`
<c4ai-feedback-container
api-key="some-api-key"
user="[email protected]"
model="">
<c4ai-output-container>
<p>Hello, How can i help you today</p>
</c4ai-output-container>
<c4ai-input-container>
<p>Hello! how are you?</p>
</c4ai-input-container>
<c4ai-output-container>
<p>I'm just a computer program, but thanks for asking!</p>
</c4ai-output-container>
<c4ai-input-container>
<p>How's weather today outside?</p>
</c4ai-input-container>
<c4ai-output-container>
<p>It's 15.0 degree celcius today</p>
</c4ai-output-container>
</c4ai-feedback-container>
`,
};
38 changes: 38 additions & 0 deletions packages/feedback/__stories__/input-container.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* @license
*
* Copyright IBM Corp. 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import '../components/input-container/input-container'
import { html } from 'lit';

/**
* More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction
*/
export default {
title: 'Components/Input container/Input container',
priyanshu891 marked this conversation as resolved.
Show resolved Hide resolved
tags: ['autodocs'],
};

/**
* More on writing stories with args: https://storybook.js.org/docs/web-components/writing-stories/args
*
* @type {{args: {label: string}, render: (function(*): TemplateResult<1>)}}
*/
export const Default = {
args: {
label: 'Input container',
},

/**
* Renders the template for Storybook
* @param {object} args Storybook arguments
* @returns {TemplateResult<1>}
*/
render: (args) =>

Check failure on line 36 in packages/feedback/__stories__/input-container.stories.js

View workflow job for this annotation

GitHub Actions / lint

'args' is defined but never used. Allowed unused args must match /^_/u
html`<c4ai-input-container content="Hello! This text is inside feedback container"/>`
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @license
*
* Copyright IBM Corp. 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import { customElement } from 'lit/decorators.js';
// need to set up package to import global files like the one below. Hardcoding
//the `c4ai`prefixes for now

// import settings from '../../globals/settings.js';
import { FeedbackContainer } from './src/feedback-container.template.js';

/**
* Component extending the @carbon/web-components' button
*/
@customElement(`c4ai-feedback-container`)
class C4AIFeedbackContainer extends FeedbackContainer {}

export default C4AIFeedbackContainer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
/**
* @license
*
* Copyright IBM Corp. 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import { LitElement, html, css } from 'lit';
import { property, state } from 'lit/decorators.js';

import '@carbon/web-components/es/components/textarea/index.js';
import '@carbon/web-components/es/components/radio-button/index.js';
import '@carbon/web-components/es/components/button/index.js';

export class FeedbackContainer extends LitElement {

Check failure on line 17 in packages/feedback/components/feedback-container/src/feedback-container.template.ts

View workflow job for this annotation

GitHub Actions / lint

Missing JSDoc comment
static styles = css`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can these styles be separated out into its own file? (see extended-button component for example)

.carbon-feedback-wrapper {
position: relative;
}

.feedback_dialog {
position: absolute;
max-width: 300px;
border: 1px dashed lightcoral;
background: white;
color: black;
padding: 16px;
}

#selected-text > text-area {
background-color: red;
}

.bulb-icon {
position: absolute;
}
`;

@state()
isModelOpen = false;

@state()
selection;

@state()
selectedText = '';

@state()
range;

@state()
minOffset = 0;
@state()
maxOffset = 0;
@state()
offset_x = 0;
@state()
offset_y = 0;

@property({ attribute: 'api-key' })

Check failure on line 62 in packages/feedback/components/feedback-container/src/feedback-container.template.ts

View workflow job for this annotation

GitHub Actions / lint

Type string trivially inferred from a string literal, remove type annotation
private _api_key: string = '';

@property({ attribute: 'user' })

Check failure on line 65 in packages/feedback/components/feedback-container/src/feedback-container.template.ts

View workflow job for this annotation

GitHub Actions / lint

Type string trivially inferred from a string literal, remove type annotation
private _user_id: string = '';

@property({ attribute: 'ai-model' })

Check failure on line 68 in packages/feedback/components/feedback-container/src/feedback-container.template.ts

View workflow job for this annotation

GitHub Actions / lint

Type string trivially inferred from a string literal, remove type annotation
private _model_id: string = '';

get api_key() {

Check failure on line 71 in packages/feedback/components/feedback-container/src/feedback-container.template.ts

View workflow job for this annotation

GitHub Actions / lint

Missing JSDoc comment
return this._api_key;
}

get user_id() {

Check failure on line 75 in packages/feedback/components/feedback-container/src/feedback-container.template.ts

View workflow job for this annotation

GitHub Actions / lint

Missing JSDoc comment
return this._user_id;
}

get model_id() {
return this._model_id;
}

@state()
generation_id?: string = '';

@state()
app_id?: number;

static properties = {
formData: {
feedback_content: '',
},
};

constructor() {
super();
this.formData = {
feedback_content: '',
feedback_value: '',
};
}

handleTextArea(event) {
console.log(event?.target.value);
this.formData.feedback_content = event?.target.value;
}

handleFeedRadio(event) {
console.log(event?.detail.value);
this.formData.feedback_value = event?.detail.value;
}

handleFormData() {
this.recordFeedback();
this.selectedText = '';
this.selection = '';
this.formData = {};
this.isModelOpen = false;
}



handleTextSelection() {
this.selection = window.getSelection();
const fullText = this.selection?.focusNode?.textContent;
const selectedText = this.selection?.toString().trim();

if (selectedText) {
this.selectedText = selectedText;
this.setAttribute('selected', '');
} else {
this.removeAttribute('selected');
}

if (this.selectedText) {
this.range = window.getSelection()?.getRangeAt(0).getBoundingClientRect();
this.minOffset = Math.min(
this.selection.anchorOffset,
this.selection.focusOffset
);
this.maxOffset = Math.max(
this.selection.anchorOffset,
this.selection.focusOffset
);
this.offset_x = this.range?.right + 16;
this.offset_y = this.selection.focusNode.parentElement.offsetTop - 18;
} else {
// this.selection = null
}
}

// connectedCallback(): void {
// super.connectedCallback();
// this.addEventListener('click', this.handleTextSelection);
// // document.body.addEventListener('click', this.handleBodyClick.bind(this))
// // document.onclick = e => this.selection = null
// console.log('Connected');
// }

// disconnectedCallback() {
// super.disconnectedCallback();
// // window.removeEventListener('keydown', this._handleKeydown);
// console.log('Disconnected');
// }

openModal() {
this.formData.feedback_content = this.selectedText;
return html`
<div
class="feedback_dialog"
style="top: ${-16}px; left: ${this.range?.left}px">
<cds-textarea
rows="2"
value=${this.formData.feedback_content}
id="selected-text"
@input=${this.handleTextArea}>
<span slot="label-text">Selected Text:</span>
</cds-textarea>

<cds-radio-button-group
label-position="right"
orientation="vertical"
name="radio-group"
@cds-radio-button-group-changed=${this.handleFeedRadio}
defaultSelected="harmful">
<cds-radio-button
value="harmful"
label-text="Harmful"></cds-radio-button>
<cds-radio-button
value="not_harmful"
label-text="Not harmful"></cds-radio-button>
<cds-radio-button
value="something_else"
label-text="Something else"></cds-radio-button>
</cds-radio-button-group>
<cds-button
@click=${this.handleFormData}
size="sm"
style="padding-top:8px"
buttonClassName="save-btn">
Save
</cds-button>
</div>
`;
}

bulb() {
return html`
<div
@click=${this.toggle}
class="bulb-icon"
style="top: ${-32}px; left: ${this.range?.left}px">
<svg
height="24px"
width="24px"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
xmlns:xlink="http://www.w3.org/1999/xlink"
enable-background="new 0 0 512 512"
fill="#000000">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g
id="SVGRepo_tracerCarrier"
stroke-linecap="round"
stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<g>
<g fill="#e1df93">
<path
d="m346.1,45.3c-28.7-25.6-67.3-37.8-105.9-33.5-60.7,6.9-110.4,55.7-118.4,116.2-4.7,35.9 4.5,71.4 26.2,99.8 57,74.9 49.5,150.2 49.5,150.2 0,5.8 4.7,10.4 10.4,10.4h96.1c5.8,0 10.4-4.7 10.4-10.4 0,0-9.5-68.7 46.9-146.9 18-25 30-52 30-84.9 5.68434e-14-38.4-16.5-75.2-45.2-100.9zm-1,172.8c-32.1,39.8-50.3,91.2-51.5,148.1h-27.2v-166.4c0-5.8-4.7-10.4-10.4-10.4s-10.4,4.7-10.4,10.4v166.4h-27.2c0-52.3-18.6-104.5-53.7-150.9-18.2-24.1-26.1-54.1-22.1-84.5 6.7-51.1 48.8-92.4 100-98.2 33.2-3.7 65,6.3 89.6,28.3 24.3,21.7 38.3,52.8 38.3,85.4-5.68434e-14,26.5-8.8,51.3-25.4,71.8z"></path>
<path
d="m340.1,416.8h-168.2c-5.8,0-10.4,4.7-10.4,10.4 0,5.8 4.7,10.4 10.4,10.4h11c5.1,35.8 35.9,63.4 73,63.4s68-27.6 73-63.4h11c5.8,0 10.4-4.7 10.4-10.4 0.2-5.8-4.5-10.4-10.2-10.4zm-84.1,63.3c-25.6,0-47.1-18.3-51.9-42.5h103.9c-4.9,24.2-26.4,42.5-52,42.5z"></path>
</g>
</g>
</g>
</svg>
</div>
`;
}

toggle() {
this.isModelOpen = !this.isModelOpen;
}

render() {
return html`
<div class="carbon-feedback-wrapper">
${this.selection ? this.bulb() : ''}
<slot></slot>
${this.isModelOpen ? this.openModal() : ''}
</div>
`;
}
}
Loading
Loading