added a set of new Vue files and rewrite download and search frontend;
This commit is contained in:
1
img/folder.svg
Normal file
1
img/folder.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="42" version="1.1" height="42"><path d="m1.5 2c-0.25 0-0.5 0.25-0.5 0.5v11c0 0.26 0.24 0.5 0.5 0.5h13c0.26 0 0.5-0.241 0.5-0.5v-9c0-0.25-0.25-0.5-0.5-0.5h-6.5l-2-2z" fill="#0082C9" style="fill:#0082C9" /></svg>
|
||||
|
After Width: | Height: | Size: 277 B |
156
src/App.vue
Normal file
156
src/App.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<section v-if="display.download" class="form-section" id="form-section">
|
||||
<mainForm
|
||||
@download="download"
|
||||
@search="search"
|
||||
@uploadfile="uploadFile"
|
||||
:uris="uris"
|
||||
></mainForm>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mainForm from "./components/mainForm";
|
||||
import toggleButton from "./components/toggleButton";
|
||||
import helper from "./helper";
|
||||
import { translate as t, translatePlural as n } from "@nextcloud/l10n";
|
||||
import Http from "./http";
|
||||
import nctable from "./ncTable";
|
||||
|
||||
const successCallback = (data, element) => {
|
||||
if (!data) {
|
||||
helper.message(t("ncdownloader", "Something must have gone wrong!"));
|
||||
return;
|
||||
}
|
||||
if (data.hasOwnProperty("error")) {
|
||||
helper.message(t("ncdownloader", data.error));
|
||||
} else if (data.hasOwnProperty("message")) {
|
||||
helper.message(t("ncdownloader", data.message));
|
||||
} else if (data.hasOwnProperty("file")) {
|
||||
helper.message(t("ncdownloader", "Downloading" + " " + data.file));
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "mainApp",
|
||||
data() {
|
||||
return {
|
||||
display: { download: true, search: false },
|
||||
uris: {
|
||||
ytd_url: helper.generateUrl("/apps/ncdownloader/youtube/new"),
|
||||
aria2_url: helper.generateUrl("/apps/ncdownloader/new"),
|
||||
search_url: helper.generateUrl("/apps/ncdownloader/search"),
|
||||
upload_url: helper.generateUrl("/apps/ncdownloader/upload"),
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
download(event) {
|
||||
let element = event.target;
|
||||
let formWrapper = element.closest("form");
|
||||
let formData = helper.getData(formWrapper);
|
||||
let inputValue = formData["text-input-value"];
|
||||
//formData.audioOnly = document.getElementById('audio-only').checked;
|
||||
if (formData.type === "youtube-dl") {
|
||||
formData["audio-only"] = formData["audio-only"] === "true";
|
||||
}
|
||||
if (!helper.isURL(inputValue) && !helper.isMagnetURI(inputValue)) {
|
||||
helper.message(t("ncdownloader", inputValue + " is Invalid"));
|
||||
return;
|
||||
}
|
||||
|
||||
let url = formWrapper.getAttribute("action");
|
||||
Http.getInstance(url)
|
||||
.setData(formData)
|
||||
.setHandler(function (data) {
|
||||
successCallback(data, element);
|
||||
})
|
||||
.send();
|
||||
helper.message(inputValue);
|
||||
},
|
||||
search(event, vm) {
|
||||
let element = event.target;
|
||||
let formWrapper = element.closest("form");
|
||||
let formData = helper.getData(formWrapper);
|
||||
let inputValue = formData["text-input-value"];
|
||||
if (inputValue && inputValue.length < 2) {
|
||||
helper.message(t("ncdownloader", "Please enter valid keyword!"));
|
||||
vm.$data.loading = 0;
|
||||
return;
|
||||
}
|
||||
helper.enabledPolling = 0;
|
||||
nctable.getInstance().loading();
|
||||
|
||||
let url = formWrapper.getAttribute("action");
|
||||
Http.getInstance(url)
|
||||
.setData(formData)
|
||||
.setHandler(function (data) {
|
||||
if (data && data.title) {
|
||||
vm.$data.loading = 0;
|
||||
const tableInst = nctable.getInstance(data.title, data.row);
|
||||
tableInst.actionLink = false;
|
||||
tableInst.rowClass = "table-row-search";
|
||||
tableInst.create();
|
||||
}
|
||||
})
|
||||
.send();
|
||||
},
|
||||
uploadFile(event, vm) {
|
||||
let element = event.target;
|
||||
const files = element.files || event.dataTransfer.files;
|
||||
if (files) {
|
||||
let formWrapper = element.closest("form");
|
||||
let url = formWrapper.getAttribute("action");
|
||||
Http.getInstance(url)
|
||||
.setHandler(function (data) {
|
||||
successCallback(data, element);
|
||||
})
|
||||
.upload(files[0]);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
mainForm,
|
||||
toggleButton,
|
||||
},
|
||||
mounted() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "css/dl_variables.scss";
|
||||
$box-height: 110px;
|
||||
|
||||
#app-content-wrapper {
|
||||
.ncdownloader-form-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-height: $box-height;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.ncdownloader-form-container.top-left {
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
#app-content-wrapper {
|
||||
#ncdownloader-form-container {
|
||||
position: relative;
|
||||
margin: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
76
src/components/actionButton.vue
Normal file
76
src/components/actionButton.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div v-bind:class="className">
|
||||
<button class="btn btn-primary" v-if="loading ^ 1" @click.prevent="handler">
|
||||
<slot>Download</slot>
|
||||
</button>
|
||||
<button class="bs-spinner" v-if="loading">
|
||||
<span
|
||||
class="spinner-border spinner-border-sm"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
disabled
|
||||
></span
|
||||
><span class="visually-hidden">Loading...</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handler(event) {
|
||||
console.log(this.enableLoading);
|
||||
if (this.enableLoading) this.loading = 1;
|
||||
this.$emit("clicked", event, this);
|
||||
},
|
||||
},
|
||||
name: "actionButton",
|
||||
props: {
|
||||
className: String,
|
||||
enableLoading: Boolean,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "../css/dl_variables.scss";
|
||||
button {
|
||||
cursor: pointer;
|
||||
border-radius: 0px;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
|
||||
border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #7d7f7d;
|
||||
border-color: #7d7f7d;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
color: #fff;
|
||||
background-color: #0b5ed7;
|
||||
border-color: #0a58ca;
|
||||
}
|
||||
</style>
|
||||
209
src/components/mainForm.vue
Normal file
209
src/components/mainForm.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<form class="main-form" id="nc-vue-unified-form" :action="path">
|
||||
<div class="options-group">
|
||||
<button class="magnet-link http-link" @click.prevent="whichType('aria2')">
|
||||
HTTP/MAGNET
|
||||
</button>
|
||||
<button class="youtube-dl-link" @click.prevent="whichType('youtube-dl')">
|
||||
Youtube-dl
|
||||
</button>
|
||||
<button class="search-torrents" @click.prevent="whichType('search')">
|
||||
Search Torrents
|
||||
</button>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<div class="download-input-container" v-if="inputType === 'download'">
|
||||
<textInput :placeholder="placeholder" :dataType="downloadType"></textInput>
|
||||
<div class="download-controls-container">
|
||||
<div v-if="checkboxes" class="checkboxes">
|
||||
<label for="audio-only" class="checkbox-label"
|
||||
><input
|
||||
type="checkbox"
|
||||
id="audio-only"
|
||||
v-model="checkedValue"
|
||||
:value="checkedValue"
|
||||
name="audio-only"
|
||||
/><span>Audio Only</span></label
|
||||
>
|
||||
</div>
|
||||
<actionButton className="download-button" @clicked="download"></actionButton>
|
||||
<uploadFile @uploadfile="uploadFile" :path="uris.upload_url"></uploadFile>
|
||||
</div>
|
||||
</div>
|
||||
<searchInput v-else @search="search"></searchInput>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
import textInput from "./textInput";
|
||||
import searchInput from "./searchInput.vue";
|
||||
import actionButton from "./actionButton";
|
||||
import uploadFile from "./uploadFile";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
checkedValue: false,
|
||||
path: this.uris.aria2_url,
|
||||
inputType: "download",
|
||||
checkboxes: false,
|
||||
downloadType: "aria2",
|
||||
placeholder: "Paste your http/magnet link here",
|
||||
};
|
||||
},
|
||||
components: {
|
||||
textInput,
|
||||
actionButton,
|
||||
searchInput,
|
||||
uploadFile,
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
whichType(type) {
|
||||
this.downloadType = type;
|
||||
if (type === "aria2") {
|
||||
this.path = this.uris.aria2_url;
|
||||
this.placeholder = "Paste your http/magnet link here";
|
||||
} else if (type === "youtube-dl") {
|
||||
this.placeholder = "Paste your video link here";
|
||||
this.path = this.uris.ytd_url;
|
||||
} else {
|
||||
this.path = this.uris.search_url;
|
||||
}
|
||||
this.checkboxes = type === "youtube-dl" ? true : false;
|
||||
this.inputType = type === "search" ? "search" : "download";
|
||||
},
|
||||
download(event) {
|
||||
this.$emit("download", event);
|
||||
},
|
||||
search(event, vm) {
|
||||
this.$emit("search", event, vm);
|
||||
},
|
||||
uploadFile(event, vm) {
|
||||
this.$emit("uploadfile", event, vm);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.uris);
|
||||
},
|
||||
name: "mainForm",
|
||||
props: {
|
||||
uris: Object,
|
||||
uri: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "../css/dl_variables.scss";
|
||||
|
||||
#nc-vue-unified-form {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: $column-height;
|
||||
.action-group {
|
||||
width: 100%;
|
||||
}
|
||||
.options-group,
|
||||
.action-group > div {
|
||||
display: flex;
|
||||
width: auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.action-group {
|
||||
flex: 2;
|
||||
& > div {
|
||||
border: 1px solid #565687;
|
||||
& > div,
|
||||
& > select {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
& > div[class$="-controls-container"] {
|
||||
display: flex;
|
||||
& div,
|
||||
& select {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.checkboxes {
|
||||
border-radius: 0%;
|
||||
}
|
||||
.download-button {
|
||||
height: $column-height;
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #2d3f59;
|
||||
border-color: #1e324f;
|
||||
border-radius: 0%;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: #191a16;
|
||||
}
|
||||
}
|
||||
|
||||
.magnet-link,
|
||||
.choose-file {
|
||||
background-color: #9f9fcd;
|
||||
border-radius: 15px 0px 0px 15px;
|
||||
}
|
||||
|
||||
.youtube-dl-link {
|
||||
background-color: #c4c4d9;
|
||||
}
|
||||
|
||||
.checkboxes {
|
||||
background-color: #c4c4d9;
|
||||
padding: 5px 1px;
|
||||
}
|
||||
input,
|
||||
button {
|
||||
margin: 0px;
|
||||
border: 0px;
|
||||
padding: 10px;
|
||||
}
|
||||
button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 1024px) {
|
||||
#nc-vue-unified-form {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
row-gap: 10px;
|
||||
height: $column-height * 3 + 10;
|
||||
|
||||
.options-group,
|
||||
.action-group > div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: $column-height;
|
||||
}
|
||||
|
||||
.action-group > div {
|
||||
border: 0px;
|
||||
flex-flow: column nowrap;
|
||||
& > div {
|
||||
margin: 5px 1px;
|
||||
}
|
||||
& > div[class$="-controls-container"] {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
.options-group {
|
||||
& > button {
|
||||
width: calc(100% / 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
52
src/components/searchInput.vue
Normal file
52
src/components/searchInput.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="search-input" id="nc-vue-search-input">
|
||||
<textInput :placeholder="placeholder" dataType="search"></textInput>
|
||||
<div class="search-controls-container">
|
||||
<div id="select-value-search">
|
||||
<select :value="selected">
|
||||
<option
|
||||
v-for="(option, key) in selectOptions"
|
||||
v-bind:key="key"
|
||||
:value="option.name"
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<actionButton className="search-button" :enableLoading="true" @clicked="search"
|
||||
>Search</actionButton
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import textInput from "./textInput";
|
||||
import actionButton from "./actionButton";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
placeholder: "Enter keyword to search",
|
||||
selected: "TPB",
|
||||
selectOptions: [
|
||||
{ name: "TPB", label: "THEPIRATEBAY" },
|
||||
{ name: "bitSearch", label: "BITSEARCH" },
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
textInput,
|
||||
actionButton,
|
||||
},
|
||||
methods: {
|
||||
search(event, btnVm) {
|
||||
this.$emit("search", event, btnVm);
|
||||
},
|
||||
},
|
||||
name: "searchInput",
|
||||
props: [],
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "../css/dl_variables.scss";
|
||||
</style>
|
||||
47
src/components/textInput.vue
Normal file
47
src/components/textInput.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="text-input-link" id="text-input-link">
|
||||
<input
|
||||
type="text"
|
||||
name="text-input-value"
|
||||
id="text-input-value"
|
||||
v-bind:placeholder="placeholder"
|
||||
v-bind:data-type="dataType"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "textinput",
|
||||
props: {
|
||||
placeholder: String,
|
||||
dataType: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "../css/dl_variables.scss";
|
||||
#text-input-link {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex: 2;
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
background-color: $bg-color;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 1024px) {
|
||||
#text-input-link {
|
||||
width: 100%;
|
||||
& > input {
|
||||
width: 100%;
|
||||
}
|
||||
& > input:focus {
|
||||
border-color: #86b7fe;
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
141
src/components/toggleButton.vue
Normal file
141
src/components/toggleButton.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<label :for="name" :class="{ active: isActive }" class="toggle-button">
|
||||
<span class="toggle-label">{{ text }}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
:disabled="disabled"
|
||||
:id="name"
|
||||
:name="name"
|
||||
:value="value"
|
||||
v-model="inputValue"
|
||||
/>
|
||||
<span class="toggle-switch"></span>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
enabledText: {
|
||||
type: String,
|
||||
default: "On",
|
||||
},
|
||||
|
||||
disabledText: {
|
||||
type: String,
|
||||
default: "Off",
|
||||
},
|
||||
|
||||
name: {
|
||||
type: String,
|
||||
default: "check-button",
|
||||
},
|
||||
|
||||
defaultStatus: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
status: this.defaultStatus,
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
defaultStatus() {
|
||||
this.status = Boolean(this.defaultStatus);
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
isActive() {
|
||||
return this.status;
|
||||
},
|
||||
|
||||
text() {
|
||||
return this.status ? this.disabledText : this.enabledText;
|
||||
},
|
||||
inputValue: {
|
||||
get() {
|
||||
return this.status;
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.status = value;
|
||||
this.$emit("change", value);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$toggle-height: 25px;
|
||||
$toggle-width: 45px;
|
||||
$bg-color: #e5e5ee;
|
||||
|
||||
.toggle-button,
|
||||
.toggle-label {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toggle-button,
|
||||
.toggle-label,
|
||||
.toggle-switch {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.toggle-button input[type="checkbox"] {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.toggle-button .toggle-switch {
|
||||
display: inline-block;
|
||||
height: $toggle-height;
|
||||
border-radius: $toggle-height / 3;
|
||||
width: $toggle-width;
|
||||
background: $bg-color;
|
||||
box-shadow: inset 0 0 1px #b1bbc7;
|
||||
position: relative;
|
||||
margin-left: 6px;
|
||||
transition: all 0.25s;
|
||||
}
|
||||
|
||||
.toggle-button .toggle-switch::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: $toggle-height;
|
||||
width: $toggle-width / 2;
|
||||
border-radius: 50%;
|
||||
left: 0;
|
||||
transform: translateX(0);
|
||||
transition: all 0.25s cubic-bezier(0.5, -0.6, 0.5, 1.6);
|
||||
}
|
||||
|
||||
.toggle-button .toggle-switch::after {
|
||||
background: #ffffff;
|
||||
box-shadow: 0 0 1px #666;
|
||||
}
|
||||
|
||||
.active .toggle-switch {
|
||||
background: #adedcb;
|
||||
box-shadow: inset 0 0 1px #adedcb;
|
||||
}
|
||||
|
||||
.active .toggle-switch::after {
|
||||
transform: translateX($toggle-width / 2);
|
||||
background: #488c68;
|
||||
box-shadow: 0 0 1px #53b883;
|
||||
}
|
||||
</style>
|
||||
61
src/components/upForm.vue
Normal file
61
src/components/upForm.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<form class="upload-form" id="nc-vue-upload-form" :action="path">
|
||||
<div class="torrent-file-header"></div>
|
||||
<div class="torrent-file-label">Torrents</div>
|
||||
<div class="icon-upload uploadfile">
|
||||
<input type="file" name="torrentfile" id="torrentfile" @change="handler" />
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "uploadForm",
|
||||
methods: {
|
||||
handler(event) {
|
||||
this.$emit("uploadfile", event, this);
|
||||
},
|
||||
},
|
||||
props: ["path"],
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "../css/dl_variables.scss";
|
||||
|
||||
#nc-vue-upload-form {
|
||||
display: flex;
|
||||
position: relative;
|
||||
row-gap: 0px;
|
||||
padding-right: 2px;
|
||||
border-radius: 15px 0px 0px 15px;
|
||||
width: 100%;
|
||||
height: $column-height;
|
||||
|
||||
.torrent-file-header {
|
||||
width: 45px;
|
||||
height: 100%;
|
||||
background: $bg-color url("../../img/folder.svg") bottom left no-repeat;
|
||||
background-size: 40px 40px;
|
||||
background-clip: border-box;
|
||||
}
|
||||
|
||||
.icon-upload.uploadfile {
|
||||
background-color: #9f9fad;
|
||||
height: 100%;
|
||||
& input[type="file"] {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
width: $upload-width;
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
|
||||
.torrent-file-label {
|
||||
padding-top: 10px;
|
||||
padding-right: 4px;
|
||||
height: 100%;
|
||||
background-color: $bg-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
38
src/components/uploadFile.vue
Normal file
38
src/components/uploadFile.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<form class="upload-file-form" id="nc-vue-upload-file-form" :action="path">
|
||||
<div class="icon-upload fileinput">
|
||||
<input type="file" name="torrentfile" id="torrentfile" accept=".torrent" @change="handler" />
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "uploadFile",
|
||||
methods: {
|
||||
handler(event) {
|
||||
this.$emit("uploadfile", event, this);
|
||||
},
|
||||
},
|
||||
props: ["path"],
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "../css/dl_variables.scss";
|
||||
#nc-vue-upload-file-form {
|
||||
.icon-upload {
|
||||
background-image: url("../../img/upload.svg");
|
||||
}
|
||||
.icon-upload.fileinput {
|
||||
background-color: #9f9fad;
|
||||
height: 100%;
|
||||
& input[type="file"] {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
width: $upload-width;
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
3
src/css/dl_variables.scss
Normal file
3
src/css/dl_variables.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
$bg-color: #e5e5ee;
|
||||
$column-height: 45px;
|
||||
$upload-width:75px;
|
||||
Reference in New Issue
Block a user