This commit is contained in:
Nazar Kanaev 2020-07-27 12:43:06 +01:00
parent 78089122e0
commit 8574c7ddb5
5 changed files with 116 additions and 79 deletions

View File

@ -9,17 +9,44 @@
</head>
<body>
<div class="wrapper d-flex vh-100" id="app" v-cloak>
<!-- feed list -->
<div class="vh-100 overflow-auto border-right flex-shrink-0" style="width: 300px">
<div class="p-2">
<div class="px-2 toolbar d-flex align-items-center mb-3">
<span class="icon mx-2">{% inline "anchor.svg" %}</span>
<div class="flex-grow-1">&nbsp;</div>
<!--<button class="toolbar-item" v-b-modal.settings-modal>-->
<b-dropdown right no-caret lazy="true" variant="link" class="settings-dropdown" toggle-class="toolbar-item px-2">
<template v-slot:button-content class="toolbar-item">
<span class="icon">{% inline "more-vertical.svg" %}</span>
</template>
<b-dropdown-item-button @click="showSettings('create')">
<span class="icon mr-1">{% inline "plus.svg" %}</span>
New Feed
</b-dropdown-item-button>
<b-dropdown-item-button @click="showSettings('manage')">
<span class="icon mr-1">{% inline "list.svg" %}</span>
Manage Feeds
</b-dropdown-item-button>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-form id="opml-import-form" enctype="multipart/form-data">
<input type="file"
id="opml-import"
@change="importOPML"
name="opml"
style="opacity: 0; width: 1px; height: 0; position: absolute;">
<label class="dropdown-item mb-0 cursor-pointer" for="opml-import">
<span class="icon mr-1">{% inline "download.svg" %}</span>
Import
</label>
</b-dropdown-form>
<b-dropdown-item href="/opml/export">
<span class="icon mr-1">{% inline "upload.svg" %}</span>
Export
</b-dropdown-item>
</b-dropdown>
</div>
<div class="p-2 ">
<div class="mb-5">
<label class="selectgroup">
<input type="radio" name="filter" value="" v-model="filterSelected">
<div class="selectgroup-label d-flex align-items-center w-100">
<span class="icon mr-2">{% inline "circle-full.svg" %}</span>
<span class="flex-fill text-left text-truncate">All</span>
<span class="counter text-right"></span>
</div>
</label>
<label class="selectgroup">
<input type="radio" name="filter" value="unread" v-model="filterSelected">
<div class="selectgroup-label d-flex align-items-center w-100">
@ -36,6 +63,14 @@
<span class="counter text-right">{{totalStats.starred || ''}}</span>
</div>
</label>
<label class="selectgroup">
<input type="radio" name="filter" value="" v-model="filterSelected">
<div class="selectgroup-label d-flex align-items-center w-100">
<span class="icon mr-2">{% inline "circle-full.svg" %}</span>
<span class="flex-fill text-left text-truncate">All</span>
<span class="counter text-right"></span>
</div>
</label>
</div>
<label class="selectgroup">
<input type="radio" name="feed" value="" v-model="feedSelected">
@ -73,6 +108,7 @@
</div>
</div>
</div>
<!-- item list -->
<div class="vh-100 d-flex flex-column border-right flex-shrink-0" style="width: 300px">
<div class="px-2 toolbar d-flex align-items-center">
<button class="toolbar-item">
@ -80,7 +116,7 @@
</button>
<input class="d-block toolbar-search" type="" v-model="itemSearch">
<div class="flex-grow-1">&nbsp;</div>
<button class="toolbar-item" @click="markItemsRead()" v-if="filterSelected != 'starred'">
<button class="toolbar-item" @click="markItemsRead()" v-if="filterSelected == 'unread'">
<span class="icon">{% inline "check.svg" %}</span>
</button>
</div>
@ -101,29 +137,24 @@
<button class="btn btn-link btn-block loading my-3" v-if="itemsPage.cur < itemsPage.num"></button>
</div>
</div>
<!-- item show -->
<div class="vh-100 d-flex flex-column w-100">
<div class="toolbar pl-2 d-flex align-items-center">
<div v-if="itemSelected">
<button class="toolbar-item" @click="toggleItemStarred(itemSelectedDetails)">
<span class="icon" v-if="itemSelectedDetails.status=='starred'" >{% inline "star-full.svg" %}</span>
<span class="icon" v-else-if="itemSelectedDetails.status!='starred'" >{% inline "star.svg" %}</span>
</button>
<button class="toolbar-item"
:disabled="itemSelectedDetails.status=='starred'"
@click="toggleItemRead(itemSelectedDetails)">
<span class="icon" v-if="itemSelectedDetails.status=='unread'">{% inline "circle-full.svg" %}</span>
<span class="icon" v-if="itemSelectedDetails.status!='unread'">{% inline "circle.svg" %}</span>
</button>
<a class="toolbar-item" :href="itemSelectedDetails.link" target="_blank">
<span class="icon">{% inline "external-link.svg" %}</span>
</a>
<button class="toolbar-item" @click="getReadable(itemSelectedDetails)">
<span class="icon">{% inline "book-open.svg" %}</span>
</button>
</div>
<div class="flex-grow-1">&nbsp;</div>
<button class="toolbar-item" v-b-modal.settings-modal>
<span class="icon">{% inline "settings.svg" %}</span>
<div class="toolbar pl-2 d-flex align-items-center" v-if="itemSelected">
<button class="toolbar-item" @click="toggleItemStarred(itemSelectedDetails)">
<span class="icon" v-if="itemSelectedDetails.status=='starred'" >{% inline "star-full.svg" %}</span>
<span class="icon" v-else-if="itemSelectedDetails.status!='starred'" >{% inline "star.svg" %}</span>
</button>
<button class="toolbar-item"
:disabled="itemSelectedDetails.status=='starred'"
@click="toggleItemRead(itemSelectedDetails)">
<span class="icon" v-if="itemSelectedDetails.status=='unread'">{% inline "circle-full.svg" %}</span>
<span class="icon" v-if="itemSelectedDetails.status!='unread'">{% inline "circle.svg" %}</span>
</button>
<a class="toolbar-item" :href="itemSelectedDetails.link" target="_blank">
<span class="icon">{% inline "external-link.svg" %}</span>
</a>
<button class="toolbar-item" @click="getReadable(itemSelectedDetails)">
<span class="icon">{% inline "book-open.svg" %}</span>
</button>
</div>
<div v-if="itemSelected" class="px-4 pt-3 pb-5 border-top overflow-auto">
@ -141,26 +172,6 @@
</div>
</div>
<b-modal id="settings-modal" hide-header hide-footer lazy>
<ul class="nav nav-tabs mx-n3 px-3 mb-3 mt-n3 pt-2 bg-light rounded-top">
<li class="nav-item">
<a class="nav-link" href="#" :class="{active: settings=='create'}" @click.prevent="settings='create'">
<span class="icon mr-1">{% inline "plus-square.svg" %}</span>
New Feed
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" :class="{active: settings=='manage'}" @click.prevent="settings='manage'">
<span class="icon mr-1">{% inline "list.svg" %}</span>
Manage Feeds
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" :class="{active: settings=='import'}" @click.prevent="settings='import'">
<span class="icon mr-1">{% inline "upload.svg" %}</span>
Import/Export
</a>
</li>
</ul>
<div v-if="settings=='create'">
<form action="" @submit.prevent="createFeed(event)">
<label for="feed-url">URL</label>
@ -174,6 +185,17 @@
</form>
</div>
<div v-else-if="settings=='manage'">
<div class="mb-5">
<form action="" @submit.prevent="createFolder(event)">
<label for="settings-new-folder">New Folder</label>
<div class="input-group">
<input id="settings-new-folder" type="text" class="form-control" name="title" required autocomplete="off">
<div class="input-group-append">
<button class="btn btn-default" type="submit">Add</button>
</div>
</div>
</form>
</div>
<div v-for="folder in foldersWithFeeds" class="mb-4" :key="folder.id">
<div class="d-flex align-items-center">
<div class="w-100" v-if="folder.id"><b>{{ folder.title }}</b></div>
@ -182,6 +204,7 @@
<template v-slot:button-content>
<span class="icon">{% inline "more-vertical.svg" %}</span>
</template>
<b-dropdown-header>{{folder.title}}</b-dropdown-header>
<b-dropdown-item @click.prevent="renameFolder(folder)">Rename</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-item class="dropdown-danger"
@ -200,6 +223,7 @@
<template v-slot:button-content>
<span class="icon">{% inline "more-vertical.svg" %}</span>
</template>
<b-dropdown-header>{{feed.title}}</b-dropdown-header>
<b-dropdown-item @click.prevent="renameFeed(feed)">Rename</b-dropdown-item>
<b-dropdown-divider v-if="folders.length"></b-dropdown-divider>
<b-dropdown-header v-if="folders.length">Move to...</b-dropdown-header>
@ -222,28 +246,6 @@
</div>
</div>
</div>
<div class="mt-5">
<form action="" @submit.prevent="createFolder(event)">
<label for="settings-new-folder">New Folder</label>
<div class="input-group">
<input id="settings-new-folder" type="text" class="form-control" name="title" required autocomplete="off">
<div class="input-group-append">
<button class="btn btn-default" type="submit">Add</button>
</div>
</div>
</form>
</div>
</div>
<div v-else-if="settings=='import'">
<form class="d-inline-block m" id="opml-import-form" enctype="multipart/form-data" style="position: relative;">
<input type="file"
id="opml-import"
@change="importOPML"
name="opml"
style="opacity: 0; width: 1px; height: 0; position: absolute;">
<label class="btn btn-default m-0" for="opml-import">Import subscriptions</label>
</form>
<a class="btn btn-default" href="/opml/export">Export subscriptions</a>
</div>
</div>
</div>

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-square"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-download"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 370 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>

After

Width:  |  Height:  |  Size: 304 B

View File

@ -355,5 +355,9 @@ var vm = new Vue({
})
}
},
showSettings: function(settings) {
this.settings = settings
this.$bvModal.show('settings-modal')
},
}
})

View File

@ -11,7 +11,7 @@ body {
}
.wrapper {
max-width: 1368px;
max-width: 1440px;
margin: 0 auto;
}
@ -45,6 +45,10 @@ select.form-control:not([multiple]):not([size]) {
.dropdown-header {
cursor: default;
max-width: 180px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dropdown-toggle-no-caret:after {
@ -69,6 +73,14 @@ select.form-control:not([multiple]):not([size]) {
padding-right: 1rem;
}
.settings-dropdown .dropdown-item:focus {
outline: none;
}
.settings-dropdown.large .dropdown-item {
padding: .5rem 1rem;
}
.dropdown-danger .dropdown-item {
color: #dc3545!important;
}
@ -100,17 +112,23 @@ select.form-control:not([multiple]):not([size]) {
background-color: transparent;
}
.b-dropdown-form:focus {
outline: none;
}
/* custom elements */
.icon {
height: 1rem;
width: 1rem;
line-height: 1;
max-height: 1rem;
}
.icon > svg {
width: 1rem;
height: 1rem;
display: block;
vertical-align: text-top;
}
.feed-icon {
@ -209,8 +227,8 @@ select.form-control:not([multiple]):not([size]) {
}
.toolbar {
height: 2rem !important;
min-height: 2rem !important;
max-height: 2rem !important;
}
.toolbar-item {
@ -221,8 +239,8 @@ select.form-control:not([multiple]):not([size]) {
border: 1px solid transparent;
padding: .25rem .5rem;
font-size: 1rem;
line-height: 2;
border-radius: .25rem;
line-height: 1;
color: inherit;
text-align: center;
@ -245,12 +263,24 @@ select.form-control:not([multiple]):not([size]) {
cursor: not-allowed;
}
.cursor-pointer {
cursor: pointer;
}
.cursor-default {
cursor: default;
}
/* content */
.content {
line-height: 1.5;
}
.content img {
max-width: 100%;
}
.content a:hover {
text-decoration: none;
}