WIP torrent search list
This commit is contained in:
@@ -1,108 +1,152 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="show" class="container">
|
<div v-if="show" class="container">
|
||||||
<h2 class="torrentHeader-text">Searching for: {{ editedSearchQuery || query }}</h2>
|
<h2 class="torrentHeader-text editable">
|
||||||
<!-- <div class="torrentHeader">
|
Searching for:
|
||||||
<span class="torrentHeader-text">Searching for: </span>
|
<span :contenteditable="!edit" @input="this.handleInput">{{
|
||||||
|
query
|
||||||
|
}}</span>
|
||||||
|
|
||||||
|
<IconSearch
|
||||||
|
class="icon"
|
||||||
|
v-if="editedSearchQuery && editedSearchQuery.length"
|
||||||
|
/>
|
||||||
|
<IconEdit v-else class="icon" @click="() => (this.edit = !this.edit)" />
|
||||||
|
</h2>
|
||||||
|
|
||||||
<span id="search" :contenteditable="editSearchQuery ? true : false" class="torrentHeader-text editable">{{ editedSearchQuery || query }}</span>
|
<div v-if="!loading">
|
||||||
|
|
||||||
|
|
||||||
<svg v-if="!editSearchQuery" class="torrentHeader-editIcon" @click="toggleEditSearchQuery">
|
|
||||||
<use xlink:href="#icon_radar"></use>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<svg v-else class="torrentHeader-editIcon" @click="toggleEditSearchQuery">
|
|
||||||
<use xlink:href="#icon_check"></use>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div v-if="listLoaded">
|
|
||||||
<div v-if="torrents.length > 0">
|
<div v-if="torrents.length > 0">
|
||||||
<!-- <ul class="filter">
|
|
||||||
<li class="filter-item" v-for="(item, index) in release_types" @click="applyFilter(item, index)" :class="{'active': item === selectedRelaseType}">{{ item }}</li>
|
|
||||||
</ul> -->
|
|
||||||
|
|
||||||
<toggle-button :options="release_types" :selected.sync="selectedRelaseType" class="toggle"></toggle-button>
|
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr class="table__header noselect">
|
<thead class="table__header noselect">
|
||||||
<th @click="sortTable('name')" :class="selectedSortableClass('name')">
|
<tr>
|
||||||
|
<th
|
||||||
|
v-for="column in columns"
|
||||||
|
:key="column"
|
||||||
|
@click="sortTable(column)"
|
||||||
|
:class="column === this.selectedColumn ? 'active' : null"
|
||||||
|
>
|
||||||
|
{{ column }}
|
||||||
|
<span v-if="prevCol === column && direction">↑</span>
|
||||||
|
<span v-if="prevCol === column && !direction">↓</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<!-- <th
|
||||||
|
@click="sortTable('name')"
|
||||||
|
:class="selectedSortableClass('name')"
|
||||||
|
>
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<span v-if="prevCol === 'name' && direction">↑</span>
|
<span v-if="prevCol === 'name' && direction">↑</span>
|
||||||
<span v-if="prevCol === 'name' && !direction">↓</span>
|
<span v-if="prevCol === 'name' && !direction">↓</span>
|
||||||
</th>
|
</th>
|
||||||
<th @click="sortTable('seed')" :class="selectedSortableClass('seed')">
|
<th
|
||||||
|
@click="sortTable('seed')"
|
||||||
|
:class="selectedSortableClass('seed')"
|
||||||
|
>
|
||||||
<span>Seed</span>
|
<span>Seed</span>
|
||||||
<span v-if="prevCol === 'seed' && direction">↑</span>
|
<span v-if="prevCol === 'seed' && direction">↑</span>
|
||||||
<span v-if="prevCol === 'seed' && !direction">↓</span>
|
<span v-if="prevCol === 'seed' && !direction">↓</span>
|
||||||
</th>
|
</th>
|
||||||
<th @click="sortTable('size')" :class="selectedSortableClass('size')">
|
<th
|
||||||
|
@click="sortTable('size')"
|
||||||
|
:class="selectedSortableClass('size')"
|
||||||
|
>
|
||||||
<span>Size</span>
|
<span>Size</span>
|
||||||
<span v-if="prevCol === 'size' && direction">↑</span>
|
<span v-if="prevCol === 'size' && direction">↑</span>
|
||||||
<span v-if="prevCol === 'size' && !direction">↓</span>
|
<span v-if="prevCol === 'size' && !direction">↓</span>
|
||||||
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
<span>Magnet</span>
|
<span>Magnet</span>
|
||||||
</th>
|
</th> -->
|
||||||
</tr>
|
</thead>
|
||||||
<tr v-for="torrent in torrents" class="table__content">
|
|
||||||
<td @click="expand($event, torrent.name)">{{ torrent.name }}</td>
|
<tbody>
|
||||||
<td @click="expand($event, torrent.name)">{{ torrent.seed }}</td>
|
<tr
|
||||||
<td @click="expand($event, torrent.name)">{{ torrent.size }}</td>
|
v-for="torrent in torrents"
|
||||||
<td @click="sendTorrent(torrent.magnet, torrent.name, $event)" class="download">
|
class="table__content"
|
||||||
<svg class="download__icon"><use xlink:href="#iconUnmatched"></use></svg>
|
:key="torrent.magnet"
|
||||||
</td>
|
>
|
||||||
</tr>
|
<td @click="expand($event, torrent.name)">{{ torrent.name }}</td>
|
||||||
|
<td @click="expand($event, torrent.name)">{{ torrent.seed }}</td>
|
||||||
|
<td @click="expand($event, torrent.name)">{{ torrent.size }}</td>
|
||||||
|
<td
|
||||||
|
@click="sendTorrent(torrent.magnet, torrent.name, $event)"
|
||||||
|
class="download"
|
||||||
|
>
|
||||||
|
<IconMagnet />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div style="
|
<div style="display: flex; justify-content: center; padding: 1rem">
|
||||||
display: flex;
|
<seasonedButton @click="resetTorrentsAndToggleEditSearchQuery"
|
||||||
justify-content: center;
|
>Edit search query</seasonedButton
|
||||||
padding: 1rem;
|
>
|
||||||
">
|
|
||||||
<seasonedButton @click="resetTorrentsAndToggleEditSearchQuery">Edit search query</seasonedButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else style="display: flex;
|
<div
|
||||||
padding-bottom: 2rem;
|
v-else
|
||||||
justify-content: center;
|
style="
|
||||||
flex-direction: column;
|
display: flex;
|
||||||
width: 100%;
|
padding-bottom: 2rem;
|
||||||
align-items: center;">
|
justify-content: center;
|
||||||
<h2>No results found</h2>
|
flex-direction: column;
|
||||||
<br />
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<h2>No results found</h2>
|
||||||
|
<br />
|
||||||
|
|
||||||
<div class="editQuery" v-if="editSearchQuery">
|
<div class="editQuery" v-if="editSearchQuery">
|
||||||
|
<seasonedInput
|
||||||
|
placeholder="Torrent query"
|
||||||
|
:value.sync="editedSearchQuery"
|
||||||
|
@enter="fetchTorrents(editedSearchQuery)"
|
||||||
|
/>
|
||||||
|
|
||||||
<seasonedInput placeholder="Torrent query" icon="_torrents" :value.sync="editedSearchQuery" @enter="fetchTorrents(editedSearchQuery)" />
|
<div style="height: 45px; width: 5px"></div>
|
||||||
|
|
||||||
<div style="height: 45px; width: 5px;"></div>
|
<seasonedButton @click="fetchTorrents(editedSearchQuery)"
|
||||||
|
>Search</seasonedButton
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
<seasonedButton @click="fetchTorrents(editedSearchQuery)">Search</seasonedButton>
|
<seasonedButton
|
||||||
|
@click="toggleEditSearchQuery"
|
||||||
|
:active="editSearchQuery ? true : false"
|
||||||
|
>Edit search query</seasonedButton
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<seasonedButton @click="toggleEditSearchQuery" :active="editSearchQuery ? true : false">Edit search query</seasonedButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="torrentloader"><i></i></div>
|
<div v-else class="torrentloader"><i></i></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import storage from '@/storage'
|
import storage from "@/storage";
|
||||||
import store from '@/store'
|
import store from "@/store";
|
||||||
import { sortableSize } from '@/utils'
|
import { sortableSize } from "@/utils";
|
||||||
import { searchTorrents, addMagnet } from '@/api'
|
import { searchTorrents, addMagnet } from "@/api";
|
||||||
|
|
||||||
import SeasonedButton from '@/components/ui/SeasonedButton'
|
import IconMagnet from "../icons/IconMagnet";
|
||||||
import SeasonedInput from '@/components/ui/SeasonedInput'
|
import IconEdit from "../icons/IconEdit";
|
||||||
import ToggleButton from '@/components/ui/ToggleButton'
|
import IconSearch from "../icons/IconSearch";
|
||||||
|
|
||||||
|
import SeasonedButton from "@/components/ui/SeasonedButton";
|
||||||
|
import SeasonedInput from "@/components/ui/SeasonedInput";
|
||||||
|
import ToggleButton from "@/components/ui/ToggleButton";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { SeasonedButton, SeasonedInput, ToggleButton },
|
components: {
|
||||||
|
IconMagnet,
|
||||||
|
IconEdit,
|
||||||
|
IconSearch,
|
||||||
|
SeasonedButton,
|
||||||
|
SeasonedInput,
|
||||||
|
ToggleButton
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
query: {
|
query: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -118,171 +162,204 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
listLoaded: false,
|
edit: true,
|
||||||
|
loading: false,
|
||||||
torrents: [],
|
torrents: [],
|
||||||
torrentResponse: undefined,
|
torrentResponse: undefined,
|
||||||
currentPage: 0,
|
currentPage: 0,
|
||||||
prevCol: '',
|
prevCol: "",
|
||||||
direction: false,
|
direction: false,
|
||||||
release_types: ['all'],
|
release_types: ["all"],
|
||||||
selectedRelaseType: 'all',
|
selectedRelaseType: "all",
|
||||||
editSearchQuery: false,
|
editSearchQuery: false,
|
||||||
editedSearchQuery: ''
|
editedSearchQuery: "",
|
||||||
}
|
|
||||||
|
columns: ["name", "seed", "size", "magnet"],
|
||||||
|
selectedColumn: null
|
||||||
|
};
|
||||||
},
|
},
|
||||||
beforeMount() {
|
created() {
|
||||||
if (localStorage.getItem('admin')) {
|
this.fetchTorrents().then(_ => this.sortTable("size"));
|
||||||
this.fetchTorrents()
|
|
||||||
}
|
|
||||||
store.dispatch('torrentModule/reset')
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectedRelaseType: function(newValue) {
|
selectedRelaseType: function (newValue) {
|
||||||
this.applyFilter(newValue)
|
this.applyFilter(newValue);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
selectedSortableClass(headerName) {
|
selectedSortableClass(headerName) {
|
||||||
return headerName === this.prevCol ? 'active' : ''
|
return headerName === this.prevCol ? "active" : "";
|
||||||
},
|
},
|
||||||
resetTorrentsAndToggleEditSearchQuery() {
|
resetTorrentsAndToggleEditSearchQuery() {
|
||||||
this.torrents = []
|
this.torrents = [];
|
||||||
this.toggleEditSearchQuery()
|
this.toggleEditSearchQuery();
|
||||||
},
|
},
|
||||||
toggleEditSearchQuery() {
|
toggleEditSearchQuery() {
|
||||||
this.editSearchQuery = !this.editSearchQuery;
|
this.editSearchQuery = !this.editSearchQuery;
|
||||||
},
|
},
|
||||||
expand(event, name) {
|
expand(event, name) {
|
||||||
const existingExpandedElement = document.getElementsByClassName('expanded')[0]
|
const existingExpandedElement =
|
||||||
|
document.getElementsByClassName("expanded")[0];
|
||||||
|
|
||||||
const clickedElement = event.target.parentNode;
|
const clickedElement = event.target.parentNode;
|
||||||
const scopedStyleDataVariable = Object.keys(clickedElement.dataset)[0]
|
const scopedStyleDataVariable = Object.keys(clickedElement.dataset)[0];
|
||||||
|
|
||||||
if (existingExpandedElement) {
|
if (existingExpandedElement) {
|
||||||
const expandedSibling = event.target.parentNode.nextSibling.className === 'expanded'
|
const expandedSibling =
|
||||||
|
event.target.parentNode.nextSibling.className === "expanded";
|
||||||
|
|
||||||
existingExpandedElement.remove()
|
existingExpandedElement.remove();
|
||||||
const table = document.getElementsByTagName('table')[0]
|
const table = document.getElementsByTagName("table")[0];
|
||||||
table.style.display = 'block'
|
table.style.display = "block";
|
||||||
|
|
||||||
if (expandedSibling) {
|
if (expandedSibling) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const nameRow = document.createElement('tr')
|
const nameRow = document.createElement("tr");
|
||||||
const nameCol = document.createElement('td')
|
const nameCol = document.createElement("td");
|
||||||
nameRow.className = 'expanded'
|
nameRow.className = "expanded";
|
||||||
nameRow.dataset[scopedStyleDataVariable] = "";
|
nameRow.dataset[scopedStyleDataVariable] = "";
|
||||||
nameCol.innerText = name
|
nameCol.innerText = name;
|
||||||
nameCol.dataset[scopedStyleDataVariable] = "";
|
nameCol.dataset[scopedStyleDataVariable] = "";
|
||||||
|
|
||||||
nameRow.appendChild(nameCol)
|
nameRow.appendChild(nameCol);
|
||||||
|
|
||||||
clickedElement.insertAdjacentElement('afterend', nameRow)
|
clickedElement.insertAdjacentElement("afterend", nameRow);
|
||||||
},
|
},
|
||||||
sendTorrent(magnet, name, event){
|
sendTorrent(magnet, name, event) {
|
||||||
this.$notifications.info({
|
this.$notifications.info({
|
||||||
title: 'Adding torrent 🦜',
|
title: "Adding torrent 🦜",
|
||||||
description: this.query,
|
description: this.query,
|
||||||
timeout: 3000
|
timeout: 3000
|
||||||
})
|
});
|
||||||
|
|
||||||
event.target.parentNode.classList.add('active')
|
event.target.parentNode.classList.add("active");
|
||||||
addMagnet(magnet, name, this.tmdb_id)
|
addMagnet(magnet, name, this.tmdb_id)
|
||||||
.catch((resp) => { console.log('error:', resp.data) })
|
.catch(resp => {
|
||||||
.then((resp) => {
|
console.log("error:", resp.data);
|
||||||
console.log('addTorrent resp: ', resp)
|
|
||||||
this.$notifications.success({
|
|
||||||
title: 'Torrent added 🎉',
|
|
||||||
description: this.query,
|
|
||||||
timeout: 3000
|
|
||||||
})
|
})
|
||||||
})
|
.then(resp => {
|
||||||
|
console.log("addTorrent resp: ", resp);
|
||||||
|
this.$notifications.success({
|
||||||
|
title: "Torrent added 🎉",
|
||||||
|
description: this.query,
|
||||||
|
timeout: 3000
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
sortTable(col, sameDirection=false) {
|
sortTable(col, sameDirection = false) {
|
||||||
if (this.prevCol === col && sameDirection === false) {
|
if (this.prevCol === col && sameDirection === false) {
|
||||||
this.direction = !this.direction
|
this.direction = !this.direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (col) {
|
if (col === "name") this.sortName();
|
||||||
case 'name':
|
else if (col === "seed") this.sortSeed();
|
||||||
this.sortName()
|
else if (col === "size") this.sortSize();
|
||||||
break
|
|
||||||
case 'seed':
|
this.prevCol = col;
|
||||||
this.sortSeed()
|
|
||||||
break
|
|
||||||
case 'size':
|
|
||||||
this.sortSize()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
this.prevCol = col
|
|
||||||
},
|
},
|
||||||
sortName() {
|
sortName() {
|
||||||
const torrentsCopy = [...this.torrents]
|
const torrentsCopy = [...this.torrents];
|
||||||
if (this.direction) {
|
if (this.direction) {
|
||||||
this.torrents = torrentsCopy.sort((a, b) => (a.name < b.name) ? 1 : -1)
|
this.torrents = torrentsCopy.sort((a, b) => (a.name < b.name ? 1 : -1));
|
||||||
} else {
|
} else {
|
||||||
this.torrents = torrentsCopy.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
this.torrents = torrentsCopy.sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sortSeed() {
|
sortSeed() {
|
||||||
const torrentsCopy = [...this.torrents]
|
const torrentsCopy = [...this.torrents];
|
||||||
if (this.direction) {
|
if (this.direction) {
|
||||||
this.torrents = torrentsCopy.sort((a, b) => parseInt(a.seed) - parseInt(b.seed));
|
this.torrents = torrentsCopy.sort(
|
||||||
|
(a, b) => parseInt(a.seed) - parseInt(b.seed)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.torrents = torrentsCopy.sort((a, b) => parseInt(b.seed) - parseInt(a.seed));
|
this.torrents = torrentsCopy.sort(
|
||||||
|
(a, b) => parseInt(b.seed) - parseInt(a.seed)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sortSize() {
|
sortSize() {
|
||||||
const torrentsCopy = [...this.torrents]
|
const torrentsCopy = [...this.torrents];
|
||||||
if (this.direction) {
|
if (this.direction) {
|
||||||
this.torrents = torrentsCopy.sort((a, b) => parseInt(sortableSize(a.size)) - parseInt(sortableSize(b.size)));
|
this.torrents = torrentsCopy.sort(
|
||||||
|
(a, b) =>
|
||||||
|
parseInt(sortableSize(a.size)) - parseInt(sortableSize(b.size))
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.torrents = torrentsCopy.sort((a, b) => parseInt(sortableSize(b.size)) - parseInt(sortableSize(a.size)));
|
this.torrents = torrentsCopy.sort(
|
||||||
|
(a, b) =>
|
||||||
|
parseInt(sortableSize(b.size)) - parseInt(sortableSize(a.size))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
findRelaseTypes() {
|
findRelaseTypes() {
|
||||||
this.torrents.forEach(item => this.release_types.push(...item.release_type))
|
this.torrents.forEach(item =>
|
||||||
this.release_types = [...new Set(this.release_types)]
|
this.release_types.push(...item.release_type)
|
||||||
|
);
|
||||||
|
this.release_types = [...new Set(this.release_types)];
|
||||||
},
|
},
|
||||||
applyFilter(item, index) {
|
applyFilter(item, index) {
|
||||||
this.selectedRelaseType = item;
|
this.selectedRelaseType = item;
|
||||||
const torrents = [...this.torrentResponse]
|
const torrents = [...this.torrentResponse];
|
||||||
|
|
||||||
if (item === 'all') {
|
if (item === "all") {
|
||||||
this.torrents = torrents
|
this.torrents = torrents;
|
||||||
this.sortTable(this.prevCol, true)
|
this.sortTable(this.prevCol, true);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.torrents = torrents.filter(torrent => torrent.release_type.includes(item))
|
this.torrents = torrents.filter(torrent =>
|
||||||
this.sortTable(this.prevCol, true)
|
torrent.release_type.includes(item)
|
||||||
|
);
|
||||||
|
this.sortTable(this.prevCol, true);
|
||||||
},
|
},
|
||||||
updateResultCountInStore() {
|
updateResultCountInStore() {
|
||||||
store.dispatch('torrentModule/setResults', this.torrents)
|
store.dispatch("torrentModule/setResults", this.torrents);
|
||||||
store.dispatch('torrentModule/setResultCount', this.torrentResponse.length)
|
store.dispatch(
|
||||||
|
"torrentModule/setResultCount",
|
||||||
|
this.torrentResponse.length
|
||||||
|
);
|
||||||
},
|
},
|
||||||
fetchTorrents(query=undefined){
|
filterDeadTorrents(torrents) {
|
||||||
this.listLoaded = false;
|
return torrents.filter(torrent => {
|
||||||
|
if (isNaN(torrent.seed)) return false;
|
||||||
|
return parseInt(torrent.seed) > 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchTorrents(query = undefined) {
|
||||||
|
this.loading = true;
|
||||||
this.editSearchQuery = false;
|
this.editSearchQuery = false;
|
||||||
|
|
||||||
searchTorrents(query || this.query, 'all', this.currentPage, storage.token)
|
return searchTorrents(query || this.query)
|
||||||
.then(data => {
|
.then(data => {
|
||||||
this.torrentResponse = [...data.results];
|
const { results } = data;
|
||||||
this.torrents = data.results;
|
if (results) {
|
||||||
this.listLoaded = true;
|
this.torrentResponse = results;
|
||||||
|
this.torrents = this.filterDeadTorrents(results);
|
||||||
|
} else {
|
||||||
|
this.torrents = [];
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then(this.updateResultCountInStore)
|
.then(this.updateResultCountInStore)
|
||||||
.then(this.findRelaseTypes)
|
.then(this.findRelaseTypes)
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
const error = e.toString()
|
console.log("e:", e);
|
||||||
this.errorMessage = error.indexOf('401') != -1 ? 'Permission denied' : 'Nothing found';
|
const error = e.toString();
|
||||||
this.listLoaded = true;
|
this.errorMessage =
|
||||||
|
error.indexOf("401") != -1 ? "Permission denied" : "Nothing found";
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleInput(event) {
|
||||||
|
this.editedSearchQuery = event.target.innerText;
|
||||||
|
console.log("edit text:", this.editedSearchQuery);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -301,11 +378,153 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$checkboxSize: 20px;
|
||||||
|
$ui-border-width: 2px;
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: $checkboxSize * 0.5;
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
display: block;
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
+ div {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: $checkboxSize + $ui-border-width * 2;
|
||||||
|
left: $checkboxSize;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
left: -$checkboxSize;
|
||||||
|
border: $ui-border-width solid var(--color-green);
|
||||||
|
width: $checkboxSize;
|
||||||
|
height: $checkboxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
left: -$checkboxSize + $ui-border-width;
|
||||||
|
top: $ui-border-width;
|
||||||
|
width: $checkboxSize + $ui-border-width;
|
||||||
|
height: $checkboxSize + $ui-border-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
+ div::after {
|
||||||
|
background-color: var(--color-green);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(checked) {
|
||||||
|
+ div::after {
|
||||||
|
background-color: var(--color-green);
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
+ div::before {
|
||||||
|
outline: 2px solid Highlight;
|
||||||
|
outline-style: auto;
|
||||||
|
outline-color: -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "./src/scss/variables";
|
@import "src/scss/variables";
|
||||||
@import "./src/scss/media-queries";
|
@import "src/scss/media-queries";
|
||||||
@import "./src/scss/elements";
|
@import "src/scss/elements";
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
color: var(--background-color);
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--text-color);
|
||||||
|
letter-spacing: 0.8px;
|
||||||
|
font-size: 1rem;
|
||||||
|
border: 1px solid var(--text-color-90);
|
||||||
|
|
||||||
|
th:first-of-type {
|
||||||
|
border-top-left-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th:last-of-type {
|
||||||
|
border-top-right-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
tr > td:first-of-type {
|
||||||
|
white-space: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr > td:not(td:first-of-type) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr > td:last-of-type {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr td:first-of-type {
|
||||||
|
border-left: 1px solid var(--text-color-90);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr td:last-of-type {
|
||||||
|
border-right: 1px solid var(--text-color-90);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:last-of-type {
|
||||||
|
td {
|
||||||
|
border-bottom: 1px solid var(--text-color-90);
|
||||||
|
}
|
||||||
|
|
||||||
|
td:first-of-type {
|
||||||
|
border-bottom-left-radius: 8px;
|
||||||
|
}
|
||||||
|
td:last-of-type {
|
||||||
|
border-bottom-right-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: var(--background-70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 0.35rem 0.25rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 24px;
|
||||||
|
fill: var(--text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.toggle {
|
.toggle {
|
||||||
max-width: unset !important;
|
max-width: unset !important;
|
||||||
@@ -323,17 +542,21 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
|
|
||||||
|
|
||||||
&-text {
|
&-text {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 14px;
|
font-size: 20px;
|
||||||
color: $green;
|
// color: $green;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
@include tablet-min {
|
.icon {
|
||||||
font-size: 16px
|
vertical-align: text-top;
|
||||||
|
margin-left: 1rem;
|
||||||
|
fill: var(--text-color);
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
// stroke: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.editable {
|
&.editable {
|
||||||
@@ -355,59 +578,67 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
// border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
margin-top: 1rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
// table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table__content, .table__header {
|
// .table__content,
|
||||||
display: flex;
|
// .table__header {
|
||||||
padding: 0;
|
// display: flex;
|
||||||
border-left: 1px solid $text-color;
|
// padding: 0;
|
||||||
border-right: 1px solid $text-color;
|
// border-left: 1px solid $text-color;
|
||||||
border-bottom: 1px solid $text-color;
|
// border-right: 1px solid $text-color;
|
||||||
|
// border-bottom: 1px solid $text-color;
|
||||||
|
|
||||||
th, td {
|
// th,
|
||||||
display: flex;
|
// td {
|
||||||
flex-direction: column;
|
// display: flex;
|
||||||
flex-basis: 100%;
|
// flex-direction: column;
|
||||||
|
// flex-basis: 100%;
|
||||||
|
|
||||||
padding: 0.4rem;
|
// padding: 0.4rem;
|
||||||
|
|
||||||
white-space: nowrap;
|
// white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
// text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
// overflow: hidden;
|
||||||
min-width: 75px;
|
// min-width: 75px;
|
||||||
}
|
// }
|
||||||
|
|
||||||
th:first-child, td:first-child {
|
// th:first-child,
|
||||||
flex: 1;
|
// td:first-child {
|
||||||
}
|
// flex: 1;
|
||||||
|
// }
|
||||||
|
|
||||||
th:not(:first-child), td:not(:first-child) {
|
// th:not(:first-child),
|
||||||
flex: 0.2;
|
// td:not(:first-child) {
|
||||||
}
|
// flex: 0.2;
|
||||||
|
// }
|
||||||
|
|
||||||
th:nth-child(2), td:nth-child(2) {
|
// th:nth-child(2),
|
||||||
flex: 0.1;
|
// td:nth-child(2) {
|
||||||
}
|
// flex: 0.1;
|
||||||
|
// }
|
||||||
|
|
||||||
@include mobile-only {
|
// @include mobile-only {
|
||||||
th:first-child, td:first-child {
|
// th:first-child,
|
||||||
display: none;
|
// td:first-child {
|
||||||
|
// display: none;
|
||||||
|
|
||||||
&.show {
|
// &.show {
|
||||||
display: block;
|
// display: block;
|
||||||
align: flex-end;
|
// align: flex-end;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
th:not(:first-child), td:not(:first-child) {
|
// th:not(:first-child),
|
||||||
flex: 1;
|
// td:not(:first-child) {
|
||||||
}
|
// flex: 1;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
.table__content {
|
.table__content {
|
||||||
td:not(:last-child) {
|
td:not(:last-child) {
|
||||||
@@ -422,58 +653,54 @@ table {
|
|||||||
border-bottom-right-radius: 3px;
|
border-bottom-right-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table__header {
|
// .table__header {
|
||||||
color: $text-color;
|
// color: $text-color;
|
||||||
text-transform: uppercase;
|
// text-transform: uppercase;
|
||||||
cursor: pointer;
|
// cursor: pointer;
|
||||||
background-color: $background-color-secondary;
|
// background-color: $background-color-secondary;
|
||||||
|
|
||||||
border-top: 1px solid $text-color;
|
// border-top: 1px solid $text-color;
|
||||||
border-top-left-radius: 3px;
|
// border-top-left-radius: 3px;
|
||||||
border-top-right-radius: 3px;
|
// border-top-right-radius: 3px;
|
||||||
|
|
||||||
th {
|
// th {
|
||||||
display: flex;
|
// display: flex;
|
||||||
flex-direction: row;
|
// flex-direction: row;
|
||||||
font-weight: 400;
|
// font-weight: 400;
|
||||||
letter-spacing: 0.7px;
|
// letter-spacing: 0.7px;
|
||||||
// font-size: 1.08rem;
|
// // font-size: 1.08rem;
|
||||||
font-size: 15px;
|
// font-size: 15px;
|
||||||
|
|
||||||
&::before {
|
// &::before {
|
||||||
content: '';
|
// content: "";
|
||||||
min-width: 0.2rem;
|
// min-width: 0.2rem;
|
||||||
}
|
// }
|
||||||
|
|
||||||
span:first-child {
|
|
||||||
margin-right: 0.6rem;
|
|
||||||
}
|
|
||||||
span:nth-child(2) {
|
|
||||||
margin-right: 0.1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
th:not(:last-child) {
|
|
||||||
border-right: 1px solid $text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// span:first-child {
|
||||||
|
// margin-right: 0.6rem;
|
||||||
|
// }
|
||||||
|
// span:nth-child(2) {
|
||||||
|
// margin-right: 0.1rem;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// th:not(:last-child) {
|
||||||
|
// border-right: 1px solid $text-color;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
.editQuery {
|
.editQuery {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
@include mobile-only {
|
@include mobile-only {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.download {
|
.download {
|
||||||
|
|
||||||
&__icon {
|
&__icon {
|
||||||
fill: $text-color-70;
|
fill: $text-color-70;
|
||||||
height: 1.2rem;
|
height: 1.2rem;
|
||||||
@@ -506,7 +733,7 @@ table {
|
|||||||
&:after {
|
&:after {
|
||||||
border: 5px solid $green;
|
border: 5px solid $green;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
content: '';
|
content: "";
|
||||||
left: 10px;
|
left: 10px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
@@ -514,6 +741,8 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@keyframes load {
|
@keyframes load {
|
||||||
100% { transform: rotate(360deg); }
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user