Files

216 lines
6.2 KiB
Plaintext
Raw Permalink Normal View History

2024-04-01 13:43:34 -03:00
import { tracked } from "@glimmer/tracking";
import Component, { Input } from "@ember/component";
import { fn } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { getOwner } from "@ember/owner";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
2024-11-19 10:57:40 +00:00
import { service } from "@ember/service";
2024-04-01 13:43:34 -03:00
import DButton from "discourse/components/d-button";
import icon from "discourse/helpers/d-icon";
import { ajax } from "discourse/lib/ajax";
import discourseDebounce from "discourse/lib/debounce";
import UppyUpload from "discourse/lib/uppy/uppy-upload";
2025-01-14 15:54:09 +11:00
import { i18n } from "discourse-i18n";
import RagUploadProgress from "./rag-upload-progress";
2024-04-01 13:43:34 -03:00
export default class RagUploader extends Component {
2024-04-01 13:43:34 -03:00
@service appEvents;
2025-03-17 05:14:53 +01:00
2024-04-01 13:43:34 -03:00
@tracked term = null;
@tracked filteredUploads = null;
@tracked ragIndexingStatuses = null;
@tracked ragUploads = null;
uppyUpload = new UppyUpload(getOwner(this), {
id: "discourse-ai-rag-uploader",
maxFiles: 20,
2024-11-05 22:10:54 +03:00
type: "discourse_ai_rag_upload",
uploadUrl:
"/admin/plugins/discourse-ai/rag-document-fragments/files/upload",
preventDirectS3Uploads: true,
uploadDone: (uploadedFile) => {
const newUpload = uploadedFile.upload;
newUpload.status = "uploaded";
2025-01-14 15:54:09 +11:00
newUpload.statusText = i18n("discourse_ai.rag.uploads.uploaded");
this.ragUploads.pushObject(newUpload);
this.debouncedSearch();
},
});
2024-04-01 13:43:34 -03:00
2024-11-20 14:43:28 +00:00
willDestroy() {
super.willDestroy(...arguments);
this.appEvents.off(
`upload-mixin:${this.uppyUpload.config}:all-uploads-complete`,
this,
"_updateTargetWithUploads"
);
}
2024-04-01 13:43:34 -03:00
didReceiveAttrs() {
super.didReceiveAttrs(...arguments);
if (this.uppyUpload.inProgressUploads?.length > 0) {
this.uppyUpload.cancelAllUploads();
2024-04-01 13:43:34 -03:00
}
this.ragUploads = this.target?.rag_uploads?.slice() || [];
this.filteredUploads = this.ragUploads;
const targetName = this.targetName || this.target?.constructor?.name;
2024-09-30 16:27:50 +09:00
if (this.ragUploads?.length && this.target?.id) {
ajax(
2024-09-30 16:27:50 +09:00
`/admin/plugins/discourse-ai/rag-document-fragments/files/status.json?target_type=${targetName}&target_id=${this.target.id}`
).then((statuses) => {
this.set("ragIndexingStatuses", statuses);
});
}
this.appEvents.on(
`upload-mixin:${this.uppyUpload.config.id}:all-uploads-complete`,
this,
2024-09-30 16:27:50 +09:00
"_updateTargetWithUploads"
);
}
2024-09-30 16:27:50 +09:00
_updateTargetWithUploads() {
this.updateUploads(this.ragUploads);
2024-04-01 13:43:34 -03:00
}
get acceptedFileTypes() {
2025-02-18 09:22:57 +11:00
if (this.args?.allowImages) {
return ".txt,.md,.png,.jpg,.jpeg";
} else {
2025-02-18 09:22:57 +11:00
return ".txt,.md,.pdf";
}
}
2024-04-01 13:43:34 -03:00
@action
submitFiles() {
this.uppyUpload.openPicker();
2024-04-01 13:43:34 -03:00
}
@action
cancelUploading(upload) {
this.uppyUpload.cancelSingleUpload({
2024-04-01 13:43:34 -03:00
fileId: upload.id,
});
}
@action
search() {
if (this.term) {
this.filteredUploads = this.ragUploads.filter((u) => {
return (
u.original_filename.toUpperCase().indexOf(this.term.toUpperCase()) >
-1
);
});
} else {
this.filteredUploads = this.ragUploads;
}
}
@action
debouncedSearch() {
discourseDebounce(this, this.search, 100);
}
@action
removeUpload(upload) {
this.ragUploads.removeObject(upload);
this.onRemove(upload);
this.debouncedSearch();
}
2024-04-01 13:43:34 -03:00
<template>
2024-09-30 16:27:50 +09:00
<div class="rag-uploader">
2025-02-18 09:22:57 +11:00
{{#if @allowImages}}
<p>{{i18n "discourse_ai.rag.uploads.description_with_images"}}</p>
{{else}}
<p>{{i18n "discourse_ai.rag.uploads.description"}}</p>
{{/if}}
2024-04-01 13:43:34 -03:00
{{#if this.ragUploads}}
2024-09-30 16:27:50 +09:00
<div class="rag-uploader__search-input-container">
<div class="rag-uploader__search-input">
{{icon
"magnifying-glass"
class="rag-uploader__search-input__search-icon"
}}
<Input
2024-09-30 16:27:50 +09:00
class="rag-uploader__search-input__input"
2025-01-14 15:54:09 +11:00
placeholder={{i18n "discourse_ai.rag.uploads.filter"}}
@value={{this.term}}
{{on "keyup" this.debouncedSearch}}
/>
</div>
2024-04-01 13:43:34 -03:00
</div>
{{/if}}
2024-04-01 13:43:34 -03:00
2024-09-30 16:27:50 +09:00
<table class="rag-uploader__uploads-list">
2024-04-01 13:43:34 -03:00
<tbody>
{{#each this.filteredUploads as |upload|}}
<tr>
<td>
2024-09-30 16:27:50 +09:00
<span class="rag-uploader__rag-file-icon">{{icon "file"}}</span>
{{upload.original_filename}}
</td>
<RagUploadProgress
@upload={{upload}}
@ragIndexingStatuses={{this.ragIndexingStatuses}}
/>
2024-09-30 16:27:50 +09:00
<td class="rag-uploader__remove-file">
2024-04-01 13:43:34 -03:00
<DButton
@icon="xmark"
2024-09-30 16:27:50 +09:00
@title="discourse_ai.rag.uploads.remove"
@action={{fn this.removeUpload upload}}
2024-11-20 14:43:28 +00:00
class="btn-flat"
2024-04-01 13:43:34 -03:00
/>
</td>
</tr>
{{/each}}
{{#each this.uppyUpload.inProgressUploads as |upload|}}
2024-04-01 13:43:34 -03:00
<tr>
2024-09-30 16:27:50 +09:00
<td><span class="rag-uploader__rag-file-icon">{{icon
2024-04-01 13:43:34 -03:00
"file"
}}</span>
{{upload.original_filename}}</td>
2024-09-30 16:27:50 +09:00
<td class="rag-uploader__upload-status">
2024-04-01 13:43:34 -03:00
<div class="spinner small"></div>
2025-01-14 15:54:09 +11:00
<span>{{i18n "discourse_ai.rag.uploads.uploading"}}
2024-04-01 13:43:34 -03:00
{{upload.uploadProgress}}%</span>
</td>
2024-09-30 16:27:50 +09:00
<td class="rag-uploader__remove-file">
2024-04-01 13:43:34 -03:00
<DButton
@icon="xmark"
2024-09-30 16:27:50 +09:00
@title="discourse_ai.rag.uploads.remove"
2024-04-01 13:43:34 -03:00
@action={{fn this.cancelUploading upload}}
2024-11-20 14:43:28 +00:00
class="btn-flat"
2024-04-01 13:43:34 -03:00
/>
</td>
</tr>
{{/each}}
</tbody>
</table>
<input
{{didInsert this.uppyUpload.setup}}
2024-04-01 13:43:34 -03:00
class="hidden-upload-field"
disabled={{this.uploading}}
type="file"
multiple="multiple"
accept={{this.acceptedFileTypes}}
2024-04-01 13:43:34 -03:00
/>
<DButton
2024-09-30 16:27:50 +09:00
@label="discourse_ai.rag.uploads.button"
2024-04-01 13:43:34 -03:00
@icon="plus"
2024-09-30 16:27:50 +09:00
@title="discourse_ai.rag.uploads.button"
2024-04-01 13:43:34 -03:00
@action={{this.submitFiles}}
class="btn-default"
/>
</div>
</template>
}