loi
This commit is contained in:
parent
80f033ff18
commit
aafaab0cb1
@ -117,13 +117,13 @@ export const routes: Routes = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'Viewallforder',
|
||||
path: 'viewallfolder',
|
||||
component: ViewallForderComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
requiredPermission: {
|
||||
action: PermissionAction.View,
|
||||
type: PermissionType.Viewallforder,
|
||||
type: PermissionType.Viewallfolder,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -340,6 +340,8 @@ import localeTr from '@angular/common/locales/tr'
|
||||
import localeUk from '@angular/common/locales/uk'
|
||||
import localeZh from '@angular/common/locales/zh'
|
||||
import localeVi from '@angular/common/locales/vi'
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ViewallForderComponent } from './components/folder-management/viewall-forder/viewall-forder.component'
|
||||
|
||||
registerLocaleData(localeAf)
|
||||
registerLocaleData(localeAr)
|
||||
@ -382,6 +384,7 @@ function initializeApp(settings: SettingsService) {
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ViewallForderComponent,
|
||||
AppComponent,
|
||||
DocumentListComponent,
|
||||
DocumentDetailComponent,
|
||||
@ -493,6 +496,7 @@ function initializeApp(settings: SettingsService) {
|
||||
DragDropModule,
|
||||
NgxBootstrapIconsModule.pick(icons),
|
||||
NgxFilesizeModule,
|
||||
CommonModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
@ -173,11 +173,11 @@
|
||||
</h6>
|
||||
<ul class="nav flex-column mb-2">
|
||||
<li class="nav-item app-link"
|
||||
*pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Viewallforder }">
|
||||
<a class="nav-link" routerLink="Viewallforder" routerLinkActive="active" (click)="closeMenu()"
|
||||
ngbPopover="viewallforder" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end"
|
||||
*pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Viewallfolder }">
|
||||
<a class="nav-link" routerLink="viewallfolder" routerLinkActive="active" (click)="closeMenu()"
|
||||
ngbPopover="viewallfolder" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end"
|
||||
container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
||||
<i-bs class="me-1" name="Personal"></i-bs><span> <ng-container i18n>Personal document</ng-container></span>
|
||||
<i class="fa-regular fa-folder-open"></i><span> <ng-container i18n>Personal document</ng-container></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item app-link"
|
||||
|
@ -1,156 +1,68 @@
|
||||
<div class="viewforder-header">
|
||||
<div class="search-new">
|
||||
<form class="myform" action="">
|
||||
<div class="folder-container">
|
||||
<div class="sub-folder-container">
|
||||
|
||||
</div>
|
||||
<div class="folder-left" id="folderLeft">
|
||||
<div class="folder-left-1">
|
||||
<div class="folder-left-search">
|
||||
<button class="search"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
<input placeholder="Tìm Kiếm" class="serch" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div id="folders-container" class="folder">
|
||||
<!-- Folders and Documents will be added dynamically here -->
|
||||
</div>
|
||||
<div id="documents-container" class="documents">
|
||||
</div>
|
||||
<div class="resize-handle"></div>
|
||||
</div>
|
||||
<div class="folder-right">
|
||||
<div class="folder-search">
|
||||
<div class="folder-right-tim"></div>
|
||||
<div class="folder-right-search">
|
||||
<button> <i class="fa-solid fa-magnifying-glass"></i> </button>
|
||||
<input type="text" placeholder="Search">
|
||||
</form>
|
||||
<div class="add-viewforder">
|
||||
<button class="addforder"><i class="fa-solid fa-folder-plus"></i> Tạo thư mục mới</button>
|
||||
<input type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="titel">
|
||||
<p>Show</p>
|
||||
<select name="Show" id="showSelect">
|
||||
<option value="16" >16</option>
|
||||
<option value="36">36</option>
|
||||
<option value="66">66</option>
|
||||
</select>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const defaultOption = document.querySelector('#showSelect option[selected]');
|
||||
if (defaultOption) {
|
||||
defaultOption.textContent = 'Show ' + defaultOption.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<h1 style="margin-left: 10px;">Forder</h1>
|
||||
</div>
|
||||
<div class="conten">
|
||||
<div *ngFor="let folder of folders" class="product-forder">
|
||||
<i class="fa-solid fa-folder"></i>
|
||||
<p>{{ folder.name }}</p>
|
||||
<i class="fa-solid fa-ellipsis-vertical" onclick="toggleDropdown(this)"></i>
|
||||
<div class="submenu">
|
||||
<ul>
|
||||
<li><a href="#">Delete</a></li>
|
||||
<li><a href="#">Reaname</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('click', function(event) {
|
||||
const submenus = document.querySelectorAll('.submenu');
|
||||
const dropdownIcons = document.querySelectorAll('.fa-ellipsis-vertical');
|
||||
|
||||
for (let i = 0; i < submenus.length; i++) {
|
||||
const submenu = submenus[i];
|
||||
const dropdownIcon = dropdownIcons[i];
|
||||
|
||||
const isClickInside = dropdownIcon.contains(event.target);
|
||||
|
||||
if (!isClickInside) {
|
||||
submenu.classList.remove('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function toggleDropdown(icon) {
|
||||
const submenu = icon.nextElementSibling;
|
||||
submenu.classList.toggle('active');
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
</script>
|
||||
</div>
|
||||
<div style="margin-top: 20px;" class="titel">
|
||||
<p>Show</p>
|
||||
<select name="Show" id="showSelect">
|
||||
<option value="16" >16</option>
|
||||
<option value="36">36</option>
|
||||
<option value="66">66</option>
|
||||
</select>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const defaultOption = document.querySelector('#showSelect option[selected]');
|
||||
if (defaultOption) {
|
||||
defaultOption.textContent = 'Show ' + defaultOption.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<h2 style="margin-left: 10px;">Documents</h2>
|
||||
</div>
|
||||
<div class="conten-tailieu">
|
||||
<div style="display: none;" class="conten-tailieu-submenu">
|
||||
<ul>
|
||||
<li><a href="#"><i class="fa-solid fa-folder"></i></a></li>
|
||||
<li><a href="#"><i class="fa-solid fa-trash"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<table id="myTable">
|
||||
<div class="folder-right-conten">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Document name</th>
|
||||
<th>Last modified <i class="fa-solid fa-caret-down"></i><i class="fa-solid fa-arrow-right-long"></i></th>
|
||||
<th>File size</th>
|
||||
<td>Name</td>
|
||||
<td>Data modified</td>
|
||||
<td>Type</td>
|
||||
<td>Size</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let document of documents">
|
||||
<td>{{ document.original_filename }}</td>
|
||||
<td>{{ document.modified | date:'medium' }}</td>
|
||||
<td>{{ calculateFileSize(document.archive_checksum) }}</td>
|
||||
<tr>
|
||||
<td>
|
||||
<i class="fa-solid fa-folder"></i>
|
||||
<p>Folder 1</p>
|
||||
</td>
|
||||
<td>11/10/2002</td>
|
||||
<td>
|
||||
<p>File Folder</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>2 KB</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i class="fa-solid fa-file"></i>
|
||||
<p>Document</p>
|
||||
</td>
|
||||
<td>11/10/2002</td>
|
||||
<td>
|
||||
<p>txt</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>2 KB</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const table = document.getElementById('myTable');
|
||||
let selectedRows = [];
|
||||
|
||||
table.addEventListener('click', function(event) {
|
||||
const target = event.target.closest('tr'); // Find closest parent <tr>
|
||||
if (!target) return;
|
||||
|
||||
const isCtrlPressed = event.ctrlKey || event.metaKey; // Check if Ctrl or Cmd key is pressed
|
||||
|
||||
if (isCtrlPressed) {
|
||||
if (selectedRows.includes(target)) {
|
||||
// Deselect row
|
||||
selectedRows = selectedRows.filter(row => row !== target);
|
||||
target.classList.remove('selected');
|
||||
} else {
|
||||
// Select row
|
||||
selectedRows.push(target);
|
||||
target.classList.add('selected');
|
||||
}
|
||||
} else {
|
||||
// Clear all selections
|
||||
selectedRows.forEach(row => row.classList.remove('selected'));
|
||||
selectedRows = [target];
|
||||
target.classList.add('selected');
|
||||
}
|
||||
|
||||
// Show or hide .conten-tailieu-submenu based on selection
|
||||
const submenu = document.querySelector('.conten-tailieu-submenu');
|
||||
if (selectedRows.length > 0) {
|
||||
submenu.style.display = 'block';
|
||||
} else {
|
||||
submenu.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Hide submenu if user clicks outside
|
||||
document.addEventListener('click', function(event) {
|
||||
if (!event.target.closest('.conten-tailieu-submenu') && !event.target.closest('table')) {
|
||||
// Clear all selections and hide submenu
|
||||
selectedRows.forEach(row => row.classList.remove('selected'));
|
||||
selectedRows = [];
|
||||
const submenu = document.querySelector('.conten-tailieu-submenu');
|
||||
submenu.style.display = 'none';
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
@ -1,224 +1,253 @@
|
||||
.viewforder-header {
|
||||
body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-new {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
margin: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.myform {
|
||||
margin-top: 10px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
|
||||
&:active {
|
||||
cursor: progress;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 10px 10px;
|
||||
width: 400px;
|
||||
margin-left: -6px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-viewforder {
|
||||
margin-top: 10px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.viewforder-header .addforder {
|
||||
padding: 10px 10px;
|
||||
margin-left: 50px;
|
||||
color: aliceblue;
|
||||
background-color: rgb(236, 72, 72);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
|
||||
&:active {
|
||||
cursor: progress;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-folder-plus {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.conten {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
flex-wrap: wrap;
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
.product-forder {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-radius: 10px;
|
||||
padding: 0 10px;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
background-color: rgba(128, 128, 128, 0.585);
|
||||
|
||||
p {
|
||||
margin-left: -40%;
|
||||
}
|
||||
|
||||
&:active {
|
||||
cursor: progress;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-ellipsis-vertical {
|
||||
cursor: wait;
|
||||
padding: 3px 3px;
|
||||
}
|
||||
|
||||
.submenu {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: auto;
|
||||
margin-left: 190px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s, transform 0.3s;
|
||||
transform: translateY(-100%);
|
||||
|
||||
ul li {
|
||||
list-style-type: none;
|
||||
padding: 5px 5px;
|
||||
border: 1px solid gray;
|
||||
background-color: rgba(0, 0, 0, 0.804);
|
||||
|
||||
a {
|
||||
color: aliceblue;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
.folder-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0%);
|
||||
}
|
||||
|
||||
.product-forder & {
|
||||
transform-origin: top;
|
||||
}
|
||||
|
||||
.product-forder ul {
|
||||
transform-origin: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.titel {
|
||||
.folder-container .folder-left {
|
||||
width: 30%;
|
||||
position: relative;
|
||||
min-width: 100px;
|
||||
height: 100vh;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
background: rgba(37, 36, 36, 0.845);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#showSelect {
|
||||
padding: 5px 5px;
|
||||
}
|
||||
.conten-tailieu{
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
height: auto;
|
||||
background-color: rgb(204, 202, 202);
|
||||
}
|
||||
.conten-tailieu {
|
||||
width: 100%;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
td:nth-child(2),
|
||||
td:nth-child(3) {
|
||||
text-align: right;
|
||||
}
|
||||
th:nth-child(2),
|
||||
th:nth-child(3) {
|
||||
text-align: center;
|
||||
}
|
||||
tbody th:nth-child(2),
|
||||
tbody th:nth-child(3),
|
||||
tbody td:nth-child(2),
|
||||
tbody td:nth-child(3) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.selected {
|
||||
background-color: lightblue;
|
||||
}
|
||||
.fa-arrow-right-long {
|
||||
display: inline-block;
|
||||
transform: rotate(90deg);
|
||||
|
||||
padding: 0 15px;
|
||||
}
|
||||
.conten-tailieu-submenu{
|
||||
position: fixed;
|
||||
display: none;
|
||||
z-index: 10000;
|
||||
.resize-handle {
|
||||
background-color: #f0f0f0;
|
||||
cursor: ew-resize;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 40%;
|
||||
width: 40px;
|
||||
height: auto;
|
||||
background-color: white;
|
||||
}
|
||||
.folder-container .folder-right {
|
||||
width: 70%;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.folder-left-1 {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 1px 0px 1px 1px black;
|
||||
}
|
||||
.conten-tailieu-submenu ul li{
|
||||
list-style-type: none;
|
||||
.folder-left-search {
|
||||
width: 85%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
box-shadow: 0 0 3px 0 gold;
|
||||
}
|
||||
.conten-tailieu-submenu .fa-solid{
|
||||
padding: 5px 12px;
|
||||
font-size: 18px;
|
||||
.folder-left-search .serch {
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
border-left: none;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
.folder-left-search .serch:focus {
|
||||
outline: none;
|
||||
}
|
||||
.serch:focus + .folder-left-search {
|
||||
border: 5px solid gold;
|
||||
}
|
||||
.folder-left-search .search {
|
||||
width: 10%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
border-right: none;
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
.folder{
|
||||
width: 95%;
|
||||
height: auto;
|
||||
}
|
||||
#folders-container{
|
||||
margin-top: 20px;
|
||||
}
|
||||
.documents {
|
||||
width: 95%;
|
||||
height: auto;
|
||||
}
|
||||
.folder-cha{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
margin-top: 2%;
|
||||
text-align: left;
|
||||
}
|
||||
.folder-cha P{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
.folder-cha .fa-solid{
|
||||
color: gold;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.folder-cha .fa-chevron-right{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
.folder-cha .fa-folder{
|
||||
color: goldenrod;
|
||||
}
|
||||
.folder-con{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
.folder-con P{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
.foder{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
.folder-con .fa-solid{
|
||||
color: gold;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.folder-con .fa-chevron-right{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
.folder-con .fa-folder{
|
||||
color: goldenrod;
|
||||
}
|
||||
#folders-container{
|
||||
margin-left: -10%;
|
||||
}
|
||||
.docoment{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
}
|
||||
.docomenta,
|
||||
.document-container{
|
||||
margin-left: 7%;
|
||||
}
|
||||
p{
|
||||
color: aliceblue;
|
||||
}
|
||||
.folder {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.folder .ke {
|
||||
background: #f0f0f0;
|
||||
width: 1px;
|
||||
height: 180%;
|
||||
z-index: 10000;
|
||||
position: absolute;
|
||||
left: 8.5%;
|
||||
top: 60%;
|
||||
display: none;
|
||||
transform: translateY(-15%);
|
||||
}
|
||||
.folder-search{
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.folder-right-tim{
|
||||
width: 60%;
|
||||
height: 40px;
|
||||
background: rgba(128, 128, 128, 0.534);
|
||||
border-radius: 5px;
|
||||
|
||||
margin-left: 10px;
|
||||
}
|
||||
.folder-right-search{
|
||||
width: 30%;
|
||||
height: 40px;
|
||||
background: rgba(128, 128, 128, 0.449);
|
||||
border-radius: 5px;
|
||||
margin-left: 50px;
|
||||
display: flex;
|
||||
}
|
||||
.folder-right-search button{
|
||||
cursor: pointer;
|
||||
padding: 11px 15px;
|
||||
border-right: none;
|
||||
}
|
||||
.folder-right-search input{
|
||||
border-left: none;
|
||||
width: 100%;
|
||||
}
|
||||
.folder-right-conten{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 20px 0;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
table td{
|
||||
color: black;
|
||||
}
|
||||
table thead {
|
||||
background-color: #007bff25;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
table thead tr {
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
table thead td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tbody tr {
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
table tbody tr:nth-of-type(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
table tbody tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
table tbody td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
}
|
||||
tbody td p{
|
||||
color: black;
|
||||
}
|
||||
|
||||
table tbody td i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
table tbody td p {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
@ -1,26 +1,230 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FoldersService } from 'src/app/services/rest/folders.service';
|
||||
import { Document, Folders } from 'src/app/data/folders';
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-viewall-forder',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
selector: 'app-view-all-folder',
|
||||
templateUrl: './viewall-forder.component.html',
|
||||
styleUrl: './viewall-forder.component.scss'
|
||||
styleUrls: ['./viewall-forder.component.scss']
|
||||
})
|
||||
export class ViewallForderComponent {
|
||||
folders: any[] = [];
|
||||
documents: any[] = [];
|
||||
export class ViewAllFolderComponent implements OnInit {
|
||||
folders: Folders[] = [];
|
||||
documents: Document[] = [];
|
||||
|
||||
constructor(private foldersService: FoldersService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.foldersService.getFoldersAndDocuments().subscribe(data => {
|
||||
this.foldersService.getFoldersAndDocuments().subscribe({
|
||||
next: data => {
|
||||
this.folders = data.folders;
|
||||
this.documents = data.documents;
|
||||
this.initializeFolders();
|
||||
this.initializeDocuments();
|
||||
this.addEventListeners();
|
||||
},
|
||||
error: error => {
|
||||
console.error('Error fetching data:', error);
|
||||
// Xử lý lỗi theo yêu cầu của bạn
|
||||
}
|
||||
});
|
||||
}
|
||||
calculateFileSize(checksum: string): string {
|
||||
return checksum.length.toString() + ' bytes';
|
||||
|
||||
initializeFolders(): void {
|
||||
const foldersContainer = document.getElementById('folders-container');
|
||||
if (foldersContainer) {
|
||||
foldersContainer.innerHTML = '';
|
||||
|
||||
const createFolders = (parentId: number | null, parentDiv: HTMLElement | null) => {
|
||||
this.folders.forEach(folder => {
|
||||
if (folder.parent_folder_id === parentId) {
|
||||
const folderHTML = this.createFolderHTML(folder, parentDiv);
|
||||
createFolders(folder.id, folderHTML.querySelector('.children-container') as HTMLElement);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.folders.forEach(folder => {
|
||||
if (folder.parent_folder_id === null) {
|
||||
const folderHTML = this.createFolderHTML(folder);
|
||||
foldersContainer.appendChild(folderHTML);
|
||||
this.documents.forEach(doc => {
|
||||
if (doc.folder_id === folder.id) {
|
||||
const documentHTML = this.createDocumentHTML(doc);
|
||||
folderHTML.querySelector('.children-container')?.appendChild(documentHTML);
|
||||
}
|
||||
});
|
||||
createFolders(folder.id, folderHTML.querySelector('.children-container') as HTMLElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initializeDocuments(): void {
|
||||
const documentsContainer = document.getElementById('documents-container');
|
||||
const foldersContainer = document.getElementById('folders-container');
|
||||
|
||||
if (documentsContainer && foldersContainer) {
|
||||
documentsContainer.innerHTML = '';
|
||||
|
||||
const addedDocumentFilenames = new Set<string>();
|
||||
|
||||
this.documents.forEach(doc => {
|
||||
if (!addedDocumentFilenames.has(doc.filename)) {
|
||||
const folder = this.findFolderById(doc.folder_id);
|
||||
if (folder && folder.id === 71) {
|
||||
const folderDiv = this.findFolderDiv(folder.id);
|
||||
if (folderDiv) {
|
||||
const documentsContainerInFolder = folderDiv.querySelector('.documents-container');
|
||||
if (documentsContainerInFolder) {
|
||||
if (!documentsContainerInFolder.querySelector(`.document[data-document-id="${doc.id}"]`)) {
|
||||
const documentHTML = this.createDocumentHTML(doc);
|
||||
documentsContainerInFolder.appendChild(documentHTML);
|
||||
addedDocumentFilenames.add(doc.filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!documentsContainer.querySelector(`.document[data-document-id="${doc.id}"]`)) {
|
||||
const documentHTML = this.createDocumentHTML(doc);
|
||||
documentsContainer.appendChild(documentHTML);
|
||||
addedDocumentFilenames.add(doc.filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
createFolderHTML(folder: Folders, parentDiv: HTMLElement | null = null): HTMLElement {
|
||||
const folderDiv = document.createElement('div');
|
||||
folderDiv.classList.add('folder');
|
||||
folderDiv.dataset.folderId = folder.id.toString();
|
||||
|
||||
if (this.hasParentFolder(folder.id)) {
|
||||
const keDiv = document.createElement('div');
|
||||
keDiv.classList.add('ke');
|
||||
folderDiv.appendChild(keDiv);
|
||||
}
|
||||
|
||||
if (parentDiv) {
|
||||
parentDiv.appendChild(folderDiv);
|
||||
folderDiv.style.marginLeft = '0px';
|
||||
}
|
||||
|
||||
const folderIcon = document.createElement('i');
|
||||
folderIcon.classList.add('fa', 'fa-solid', 'fa-chevron-right');
|
||||
const folderIconFolder = document.createElement('i');
|
||||
folderIconFolder.classList.add('fa', 'fa-solid', 'fa-folder');
|
||||
|
||||
const folderName = document.createElement('p');
|
||||
folderName.textContent = folder.name;
|
||||
|
||||
const folderHeader = document.createElement('div');
|
||||
folderHeader.classList.add('folder-cha');
|
||||
folderHeader.appendChild(folderIcon);
|
||||
folderHeader.appendChild(folderIconFolder);
|
||||
folderHeader.appendChild(folderName);
|
||||
|
||||
folderDiv.appendChild(folderHeader);
|
||||
|
||||
const childrenContainer = document.createElement('div');
|
||||
childrenContainer.classList.add('children-container');
|
||||
childrenContainer.style.display = 'none';
|
||||
folderDiv.appendChild(childrenContainer);
|
||||
|
||||
return folderDiv;
|
||||
}
|
||||
|
||||
createDocumentHTML(doc: Document): HTMLElement {
|
||||
const documentDiv = document.createElement('div');
|
||||
documentDiv.classList.add('document');
|
||||
documentDiv.dataset.documentId = doc.id.toString();
|
||||
|
||||
const documentName = document.createElement('p');
|
||||
documentName.textContent = doc.filename;
|
||||
|
||||
const documentContainer = document.createElement('div');
|
||||
documentContainer.classList.add('document-container');
|
||||
documentContainer.appendChild(documentName);
|
||||
|
||||
documentDiv.appendChild(documentContainer);
|
||||
return documentDiv;
|
||||
}
|
||||
|
||||
hasParentFolder(folderId: number): boolean {
|
||||
return this.folders.some(folder => folder.parent_folder_id === folderId);
|
||||
}
|
||||
|
||||
findFolderById(folderId: number | null): Folders | undefined {
|
||||
return this.folders.find(folder => folder.id === folderId);
|
||||
}
|
||||
|
||||
findFolderDiv(folderId: number): HTMLElement | null {
|
||||
const foldersContainer = document.getElementById('folders-container');
|
||||
return foldersContainer?.querySelector(`.folder[data-folder-id="${folderId}"]`) as HTMLElement;
|
||||
}
|
||||
|
||||
addEventListeners(): void {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const folderLeft = document.getElementById('folderLeft');
|
||||
if (folderLeft) {
|
||||
const resizeHandle = folderLeft.querySelector('.resize-handle') as HTMLElement | null;
|
||||
if (resizeHandle) {
|
||||
let startX: number, startWidth: number;
|
||||
|
||||
resizeHandle.addEventListener('mousedown', (event: MouseEvent) => {
|
||||
startX = event.clientX;
|
||||
startWidth = parseInt(document.defaultView.getComputedStyle(folderLeft).width, 10);
|
||||
|
||||
document.addEventListener('mousemove', resizeWidth);
|
||||
document.addEventListener('mouseup', stopResize);
|
||||
});
|
||||
|
||||
const resizeWidth = (event: MouseEvent) => {
|
||||
const newWidth = startWidth + (event.clientX - startX);
|
||||
folderLeft.style.width = newWidth + 'px';
|
||||
const folderRight = document.querySelector('.folder-right') as HTMLElement | null;
|
||||
if (folderRight) {
|
||||
folderRight.style.width = `calc(100% - ${newWidth}px)`;
|
||||
}
|
||||
};
|
||||
|
||||
const stopResize = () => {
|
||||
document.removeEventListener('mousemove', resizeWidth);
|
||||
document.removeEventListener('mouseup', stopResize);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle folder open/close toggle
|
||||
const folderCha = document.querySelectorAll('.folder-cha');
|
||||
if (folderCha.length > 0) {
|
||||
folderCha.forEach(item => {
|
||||
let isOpen = false; // Track whether folder is open or closed
|
||||
const folderIcon = item.querySelector('.fa-folder');
|
||||
const chevronIcon = item.querySelector('.fa-chevron-right') as HTMLElement;
|
||||
const folder = item.closest('.folder');
|
||||
const ke = folder.querySelector('.ke');
|
||||
|
||||
item.addEventListener('click', () => {
|
||||
if (isOpen) {
|
||||
const ke = folder.querySelector('.ke') as HTMLElement;
|
||||
ke.style.display = 'none'; // Hide .ke when closing the folder
|
||||
folderIcon.classList.remove('fa-folder-open' ) ;
|
||||
folderIcon.classList.add('fa-folder');
|
||||
chevronIcon.style.transform = ''; // Reset chevron rotation
|
||||
} else {
|
||||
const ke = folder.querySelector('.ke') as HTMLElement;
|
||||
ke.style.display = 'block'; // Show .ke when opening the folder
|
||||
folderIcon.classList.remove('fa-folder');
|
||||
folderIcon.classList.add('fa-folder-open');
|
||||
chevronIcon.style.transform = 'rotate(90deg)'; // Rotate chevron
|
||||
}
|
||||
|
||||
isOpen = !isOpen; // Toggle isOpen state
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,38 @@
|
||||
import { MatchingModel } from './matching-model'
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { MatchingModel } from './matching-model';
|
||||
|
||||
export interface folders extends MatchingModel {
|
||||
|
||||
type?: string
|
||||
|
||||
parent_warehouse?: number
|
||||
|
||||
path?: string
|
||||
export interface Folders extends MatchingModel {
|
||||
id: number;
|
||||
owner_id: number;
|
||||
name: string;
|
||||
match: string;
|
||||
matching_algorithm: number;
|
||||
is_insensitive: boolean;
|
||||
parent_folder_id: number | null;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface Document {
|
||||
id: number;
|
||||
owner_id: number;
|
||||
correspondent_id: number | null;
|
||||
storage_path_id: number | null;
|
||||
folder_id: number | null;
|
||||
warehouse_id: number | null;
|
||||
title: string;
|
||||
document_type_id: number | null;
|
||||
content: string;
|
||||
mime_type: string;
|
||||
checksum: string;
|
||||
archive_checksum: string;
|
||||
created: string;
|
||||
modified: string;
|
||||
storage_type: string;
|
||||
added: string;
|
||||
filename: string;
|
||||
archive_filename: string;
|
||||
original_filename: string;
|
||||
archive_serial_number: number | null;
|
||||
}
|
@ -14,7 +14,7 @@ export enum PermissionType {
|
||||
Tag = '%s_tag',
|
||||
Warehouse = '%s_warehouse',
|
||||
Correspondent = '%s_correspondent',
|
||||
Viewallforder = '%s_viewallforder',
|
||||
Viewallfolder = '%s_viewallfolder',
|
||||
DocumentType = '%s_documenttype',
|
||||
StoragePath = '%s_storagepath',
|
||||
SavedView = '%s_savedview',
|
||||
|
@ -1,14 +1,19 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Warehouse } from 'src/app/data/warehouse'
|
||||
import { AbstractNameFilterService } from './abstract-name-filter-service';
|
||||
import { Folders, Document } from 'src/app/data/folders';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FoldersService extends AbstractNameFilterService<folders> {
|
||||
export class FoldersService extends AbstractNameFilterService<Folders> {
|
||||
constructor(http: HttpClient) {
|
||||
super(http, 'folders')
|
||||
super(http, 'folders');
|
||||
}
|
||||
|
||||
getFoldersAndDocuments(): Observable<{ folders: Folders[], documents: Document[] }> {
|
||||
return this.http.get<{ folders: Folders[], documents: Document[] }>(`${environment.apiBaseUrl}folders/folders_documents/`);
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<meta name="theme-color" content="#17541f" />
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png">
|
||||
</head>
|
||||
|
@ -2069,10 +2069,11 @@ class FolderViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin):
|
||||
def getFolderDoc(self, request):
|
||||
currentUser = request.user
|
||||
documents = list(Document.objects.filter(folder=None, owner=currentUser).order_by("-created").values())
|
||||
folders = list(Folder.objects.filter(parent_folder=None, owner=currentUser).order_by("name").values())
|
||||
folders = list(Folder.objects.filter(parent_folder=None, owner=currentUser).order_by("name"))
|
||||
folders_serialisers = FolderSerializer(folders, many = True)
|
||||
return {
|
||||
"documents": documents,
|
||||
"folders": folders,
|
||||
"folders": folders_serialisers.data,
|
||||
}
|
||||
|
||||
@action(methods=["get"], detail=False)
|
||||
@ -2089,12 +2090,13 @@ class FolderViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin):
|
||||
|
||||
|
||||
def getFolderDocById(self, fol):
|
||||
|
||||
documents = list(Document.objects.filter(folder=fol).order_by("-created").values())
|
||||
child_folders = list(Folder.objects.filter(parent_folder=fol).order_by("name").values())
|
||||
currentUser = self.request.user
|
||||
documents = list(Document.objects.filter(folder=fol, owner=currentUser).order_by("-created").values())
|
||||
child_folders = list(Folder.objects.filter(parent_folder=fol, owner=currentUser).order_by("name"))
|
||||
folders_serialisers = FolderSerializer(child_folders, many=True)
|
||||
return {
|
||||
"documents": documents,
|
||||
"folders": child_folders,
|
||||
"folders": folders_serialisers.data,
|
||||
}
|
||||
|
||||
@action(methods=["get"], detail=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user