Compare commits
	
		
			21 Commits
		
	
	
		
			v1.0.0
			...
			feat/submi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 841ee4327e | |||
| a2c00d929d | |||
| 0a84223778 | |||
| 20ad976939 | |||
| 5121aec6ee | |||
| 5bc2709231 | |||
| 53c0aca460 | |||
| cdf2ddae1c | |||
| a5c68ffd8d | |||
| 5e33d8cfef | |||
| c34a867387 | |||
| a11ad2f651 | |||
| 755bd116d5 | |||
| 9e33784781 | |||
| 470bcdd72e | |||
| d56a7d4dfe | |||
| b46e586c92 | |||
| 563eb3f1ef | |||
| 98644513ad | |||
| 3033db02b8 | |||
| 70a6ed189b | 
| @@ -123,6 +123,10 @@ img{ | |||||||
|   height: auto; |   height: auto; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .no-scroll { | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
| .wrapper{ | .wrapper{ | ||||||
|   position: relative; |   position: relative; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/api.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/api.js
									
									
									
									
									
								
							| @@ -135,14 +135,21 @@ const searchTorrents = (query, authorization_token) => { | |||||||
| const addMagnet = (magnet, name, tmdb_id) => { | const addMagnet = (magnet, name, tmdb_id) => { | ||||||
|   const url = new URL('v1/pirate/add', SEASONED_URL) |   const url = new URL('v1/pirate/add', SEASONED_URL) | ||||||
|  |  | ||||||
|   const body = { |   const body = JSON.stringify({ | ||||||
|     magnet: magnet, |     magnet: magnet, | ||||||
|     name: name, |     name: name, | ||||||
|     tmdb_id: tmdb_id |     tmdb_id: tmdb_id | ||||||
|  |   }) | ||||||
|  |   const headers = { | ||||||
|  |     'Content-Type': 'application/json', | ||||||
|  |     authorization: storage.token | ||||||
|   } |   } | ||||||
|   const headers = { authorization: storage.token } |  | ||||||
|  |  | ||||||
|   return fetch(url.href, { method: 'POST', headers, body }) |   return fetch(url.href, { | ||||||
|  |       method: 'POST', | ||||||
|  |       headers, | ||||||
|  |       body | ||||||
|  |     }) | ||||||
|     .then(resp => resp.json()) |     .then(resp => resp.json()) | ||||||
|     .catch(error => { console.error(`api error adding magnet: ${name} ${error}`); throw error }) |     .catch(error => { console.error(`api error adding magnet: ${name} ${error}`); throw error }) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,23 +32,28 @@ | |||||||
|  |  | ||||||
|         <!-- SIDEBAR ACTIONS --> |         <!-- SIDEBAR ACTIONS --> | ||||||
|         <div class="movie__actions" v-if="movie"> |         <div class="movie__actions" v-if="movie"> | ||||||
|  |           <sidebar-list-element :iconRef="'#iconNot_exsits'" :active="requested" | ||||||
|           <sidebar-list-element :iconRef="'#iconNot_exsits'" :active="matched" |             :iconRefActive="'#iconExists'" :textActive="'Already in plex 🎉'" :class="requested ? 'rotate-180' : null"> | ||||||
|             :iconRefActive="'#iconExists'" :textActive="'Already in plex 🎉'"> |  | ||||||
|  |  | ||||||
|             Not yet in plex |             Not yet in plex | ||||||
|           </sidebar-list-element> |           </sidebar-list-element> | ||||||
|  |  | ||||||
|           <sidebar-list-element @click="sendRequest" :iconRef="'#iconSent'" |           <sidebar-list-element @click="sendRequest" :iconRef="'#iconSent'" | ||||||
|             :active="requested" :textActive="'Requested to be downloaded'"> |             :active="requested" :textActive="'Requested to be downloaded'"> | ||||||
|  |  | ||||||
|             Request to be downloaded? |             Request to be downloaded? | ||||||
|           </sidebar-list-element> |           </sidebar-list-element> | ||||||
|  |  | ||||||
|           <sidebar-list-element v-if="admin" @click="showTorrents=!showTorrents" |           <sidebar-list-element v-if="admin" @click="showTorrents=!showTorrents" | ||||||
|             :iconRef="'#icon_torrents'" :active="showTorrents" |             :iconRef="'#icon_torrents'" :active="showTorrents" | ||||||
|             :supplementaryText="numberOfTorrentResults"> |             :supplementaryText="numberOfTorrentResults"> | ||||||
|  |  | ||||||
|             Search for torrents |             Search for torrents | ||||||
|           </sidebar-list-element> |           </sidebar-list-element> | ||||||
|  |  | ||||||
|  |           <sidebar-list-element @click="showIssueForm = !showIssueForm" | ||||||
|  |                                 :iconRef="null" | ||||||
|  |                                 :active="showIssueForm"> | ||||||
|  |              ⚠️  Report an issue! | ||||||
|  |           </sidebar-list-element> | ||||||
|  |  | ||||||
|           <sidebar-list-element @click="openTmdb" :iconRef="'#icon_info'"> |           <sidebar-list-element @click="openTmdb" :iconRef="'#icon_info'"> | ||||||
|             See more info |             See more info | ||||||
|           </sidebar-list-element> |           </sidebar-list-element> | ||||||
| @@ -64,14 +69,16 @@ | |||||||
|  |  | ||||||
|         <!-- MOVIE INFO --> |         <!-- MOVIE INFO --> | ||||||
|         <div class="movie__info"> |         <div class="movie__info"> | ||||||
|           <div class="movie__description" v-if="movie"> {{ movie.overview }}</div> |  | ||||||
|  |  | ||||||
|           <!-- Loading placeholder --> |           <!-- Loading placeholder --> | ||||||
|           <div v-else class="movie__description"> |           <div v-if="!movie" class="movie__description"> | ||||||
|             <loading-placeholder :count="12" /> |             <loading-placeholder :count="12" /> | ||||||
|           </div> |           </div> | ||||||
|  |  | ||||||
|           <div class="movie__details" v-if="movie"> |           <div class="movie__details" v-if="movie && !showIssueForm"> | ||||||
|  |             <div class="movie__description"> | ||||||
|  |               {{ movie.overview }} | ||||||
|  |             </div> | ||||||
|             <div v-if="movie.year" class="movie__details-block"> |             <div v-if="movie.year" class="movie__details-block"> | ||||||
|               <h2 class="movie__details-title">Release Date</h2> |               <h2 class="movie__details-title">Release Date</h2> | ||||||
|               <div class="movie__details-text">{{ movie.year }}</div> |               <div class="movie__details-text">{{ movie.year }}</div> | ||||||
| @@ -93,6 +100,17 @@ | |||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |           <div v-if="showIssueForm" class="issueForm"> | ||||||
|  |             <h2 class="movie__details-title">Report an issue</h2> | ||||||
|  |             <RadioButtons class="issueOptions" | ||||||
|  |                           :options="issueOptions" | ||||||
|  |                           :value.sync="selectedIssue" /> | ||||||
|  |             <TextArea title="Additional information" :rows="3" | ||||||
|  |                       placeholder="Placeholder text" /> | ||||||
|  |             <SeasonedButton @click="reportIssue">Report issue</SeasonedButton> | ||||||
|  |           </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <!-- TODO: change this classname, this is general  --> |         <!-- TODO: change this classname, this is general  --> | ||||||
| @@ -122,12 +140,23 @@ import Person from './Person' | |||||||
| import SidebarListElement from './ui/sidebarListElem' | import SidebarListElement from './ui/sidebarListElem' | ||||||
| import store from '@/store' | import store from '@/store' | ||||||
| import LoadingPlaceholder from './ui/LoadingPlaceholder' | import LoadingPlaceholder from './ui/LoadingPlaceholder' | ||||||
|  | import RadioButtons from './ui/RadioButtons' | ||||||
|  | import TextArea from './ui/TextArea' | ||||||
|  | import SeasonedButton from './ui/SeasonedButton' | ||||||
|  |  | ||||||
| import { getMovie, getShow, request, getRequestStatus } from '@/api' | import { getMovie, getShow, request, getRequestStatus } from '@/api' | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   props: ['id', 'type'], |   props: ['id', 'type'], | ||||||
|   components: { TorrentList, Person, LoadingPlaceholder, SidebarListElement }, |   components: { | ||||||
|  |     TorrentList, | ||||||
|  |     Person, | ||||||
|  |     LoadingPlaceholder, | ||||||
|  |     SidebarListElement, | ||||||
|  |     RadioButtons, | ||||||
|  |     TextArea, | ||||||
|  |     SeasonedButton | ||||||
|  |   }, | ||||||
|   directives: { img: img }, // TODO decide to remove or use |   directives: { img: img }, // TODO decide to remove or use | ||||||
|   data(){ |   data(){ | ||||||
|     return{ |     return{ | ||||||
| @@ -142,7 +171,9 @@ export default { | |||||||
|       requested: false, |       requested: false, | ||||||
|       admin: localStorage.getItem('admin'), |       admin: localStorage.getItem('admin'), | ||||||
|       showTorrents: false, |       showTorrents: false, | ||||||
|       compact: false |       compact: false, | ||||||
|  |       showIssueForm: false, | ||||||
|  |       selectedIssue: null | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
| @@ -177,6 +208,15 @@ export default { | |||||||
|       const tmdbType = this.type === 'show' ? 'tv' : this.type |       const tmdbType = this.type === 'show' ? 'tv' : this.type | ||||||
|       window.location.href = 'https://www.themoviedb.org/' + tmdbType + '/' + this.id |       window.location.href = 'https://www.themoviedb.org/' + tmdbType + '/' + this.id | ||||||
|     }, |     }, | ||||||
|  |     reportIssue() { | ||||||
|  |       if (this.showIssueForm) { | ||||||
|  |         this.$notifications.success({ | ||||||
|  |           title: 'Issue successfully submitted', | ||||||
|  |           description: 'Reported issue: Missing subtitles', | ||||||
|  |           timeout: 300000 | ||||||
|  |         }) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
|     id: function(val){ |     id: function(val){ | ||||||
| @@ -191,6 +231,35 @@ export default { | |||||||
|     numberOfTorrentResults: () => { |     numberOfTorrentResults: () => { | ||||||
|       let numTorrents = store.getters['torrentModule/resultCount'] |       let numTorrents = store.getters['torrentModule/resultCount'] | ||||||
|       return numTorrents !== null ? numTorrents + ' results' : null |       return numTorrents !== null ? numTorrents + ' results' : null | ||||||
|  |     }, | ||||||
|  |     issueOptions: function() { | ||||||
|  |       return [{ | ||||||
|  |           value: 'playback', | ||||||
|  |           text: 'Unable to play' | ||||||
|  |         }, { | ||||||
|  |           value: 'missing-episode', | ||||||
|  |           text: 'Missing Episode', | ||||||
|  |           subElements: this.seasonOptions | ||||||
|  |         }, { | ||||||
|  |           value: 'missing-subtitle', | ||||||
|  |           text: 'Missing subtitles' | ||||||
|  |         }] | ||||||
|  |     }, | ||||||
|  |     seasonOptions: function() { | ||||||
|  |       if (this.movie.type !== 'show') { | ||||||
|  |         return [] | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       const options = [] | ||||||
|  |       const length = this.movie.seasons; | ||||||
|  |  | ||||||
|  |       for (var i = 0; i < length; i++) { | ||||||
|  |         options.push({ | ||||||
|  |           value: i+1, | ||||||
|  |           text: `Season ${i+1}` | ||||||
|  |         }) | ||||||
|  |       } | ||||||
|  |       return options; | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   beforeDestroy() { |   beforeDestroy() { | ||||||
| @@ -224,6 +293,9 @@ export default { | |||||||
| @import "./src/scss/media-queries"; | @import "./src/scss/media-queries"; | ||||||
|  |  | ||||||
| .movie { | .movie { | ||||||
|  |   background-color: $background-color; | ||||||
|  |   color: $text-color; | ||||||
|  |  | ||||||
|   &__wrap { |   &__wrap { | ||||||
|     display: flex; |     display: flex; | ||||||
|     &--header { |     &--header { | ||||||
| @@ -237,9 +309,6 @@ export default { | |||||||
|       @include tablet-min{ |       @include tablet-min{ | ||||||
|         flex-direction: row; |         flex-direction: row; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       background-color: $background-color; |  | ||||||
|       color: $text-color; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   &__header { |   &__header { | ||||||
| @@ -360,15 +429,19 @@ export default { | |||||||
|       font-size: 13px; |       font-size: 13px; | ||||||
|       line-height: 1.8; |       line-height: 1.8; | ||||||
|       margin-bottom: 20px; |       margin-bottom: 20px; | ||||||
|  |       flex: 0 0 100%; | ||||||
|  |  | ||||||
|       @include tablet-min { |       @include tablet-min { | ||||||
|         margin-bottom: 30px; |         margin-bottom: 30px; | ||||||
|         font-size: 14px; |         font-size: 14px; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     &__details { |     &__details { | ||||||
|       &-block { |       display: flex; | ||||||
|         float: left; |       width: 100%; | ||||||
|       } |       flex-direction: row; | ||||||
|  |       flex-wrap: wrap; | ||||||
|  |  | ||||||
|       &-block:not(:last-child) { |       &-block:not(:last-child) { | ||||||
|         margin-bottom: 20px; |         margin-bottom: 20px; | ||||||
|         margin-right: 20px; |         margin-right: 20px; | ||||||
| @@ -417,4 +490,24 @@ export default { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .issueForm { | ||||||
|  |   // padding: 40px; | ||||||
|  |  | ||||||
|  |   .issueOptions { | ||||||
|  |     margin-top: 1rem; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .seasonOptions { | ||||||
|  |     margin-top: 2rem; | ||||||
|  |  | ||||||
|  |     h2 { | ||||||
|  |       margin-bottom: 1rem; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     > :not(h2) { | ||||||
|  |       margin-left: 1rem; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -32,9 +32,11 @@ export default { | |||||||
|   }, |   }, | ||||||
|   created(){ |   created(){ | ||||||
|     window.addEventListener('keyup', this.checkEventForEscapeKey) |     window.addEventListener('keyup', this.checkEventForEscapeKey) | ||||||
|  |     document.getElementsByTagName("body")[0].classList += " no-scroll"; | ||||||
|   }, |   }, | ||||||
|   beforeDestroy() { |   beforeDestroy() { | ||||||
|     window.removeEventListener('keyup', this.checkEventForEscapeKey) |     window.removeEventListener('keyup', this.checkEventForEscapeKey) | ||||||
|  |     document.getElementsByTagName("body")[0].classList.remove("no-scroll"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
|      |      | ||||||
|     <div class="search"> |     <div class="search"> | ||||||
|       <input |       <input | ||||||
|  |         ref="input" | ||||||
|         type="text" |         type="text" | ||||||
|         placeholder="Search for a movie or show" |         placeholder="Search for a movie or show" | ||||||
|         autocorrect="off" |         autocorrect="off" | ||||||
| @@ -93,6 +94,13 @@ export default { | |||||||
|     navigateUp() { |     navigateUp() { | ||||||
|       this.focus = true |       this.focus = true | ||||||
|       this.selectedResult-- |       this.selectedResult-- | ||||||
|  |       const input = this.$refs.input; | ||||||
|  |       const textLength = input.value.length | ||||||
|  |  | ||||||
|  |       setTimeout(() => { | ||||||
|  |         input.focus() | ||||||
|  |         input.setSelectionRange(textLength, textLength + 1) | ||||||
|  |       }, 1) | ||||||
|     }, |     }, | ||||||
|     handleInput(e){ |     handleInput(e){ | ||||||
|       this.selectedResult = 0 |       this.selectedResult = 0 | ||||||
|   | |||||||
| @@ -129,7 +129,11 @@ a { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| .settings { | .settings { | ||||||
|    padding: 35px; |   padding: 3rem; | ||||||
|  |  | ||||||
|  |   @include mobile-only { | ||||||
|  |     padding: 1rem; | ||||||
|  |   } | ||||||
|  |  | ||||||
|    &__header { |    &__header { | ||||||
|       margin: 0; |       margin: 0; | ||||||
|   | |||||||
							
								
								
									
										133
									
								
								src/components/ui/RadioButtons.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/components/ui/RadioButtons.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <label v-for="option in options" class="radio" @click="selected = option.value"> | ||||||
|  |       <input type="radio" v-model="selected" :value="option.value" /> | ||||||
|  |       <label>{{ option.text }}</label> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |       <div class="sub-radios" v-if="option.subElements && selected === option.value"> | ||||||
|  |         <label class="radio" v-for="elem in option.subElements"> | ||||||
|  |           <input type="radio" v-model="selectedSubItem" :value="option.value + '-' + elem.value" /> | ||||||
|  |           <label>{{ elem.text }}</label> | ||||||
|  |         </label> | ||||||
|  |       </div> | ||||||
|  |     </label> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | export default { | ||||||
|  |   props: { | ||||||
|  |     options: { | ||||||
|  |       type: Array, | ||||||
|  |       required: true | ||||||
|  |     }, | ||||||
|  |     value: { | ||||||
|  |       required: false, | ||||||
|  |       default: undefined | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       selected: this.value || this.options[0].value, | ||||||
|  |       selectedSubItem: null | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   beforeMount() { | ||||||
|  |     this.handleChange() | ||||||
|  |   }, | ||||||
|  |   watch: { | ||||||
|  |     selected() { | ||||||
|  |       this.handleChange(); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     handleChange() { | ||||||
|  |       if (this.value !== undefined) { | ||||||
|  |         this.$emit("update:value", this.selected); | ||||||
|  |       } else { | ||||||
|  |         this.$emit("changed", this.selected); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | @import "./src/scss/variables.scss"; | ||||||
|  |  | ||||||
|  | $radioSize: 16px; | ||||||
|  | $ui-border-width: 2px; | ||||||
|  |  | ||||||
|  | .sub-radios { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   flex: 0 0 100%; | ||||||
|  |   margin-left: 1rem; | ||||||
|  |    | ||||||
|  |   &:first-of-type { | ||||||
|  |     margin-top: 1rem; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .radio { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: row; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   margin-bottom: 14px; | ||||||
|  |   width: max-content; | ||||||
|  |  | ||||||
|  |   input[type="radio"] { | ||||||
|  |     display: block; | ||||||
|  |     opacity: 0; | ||||||
|  |  | ||||||
|  |     + label { | ||||||
|  |       position: relative; | ||||||
|  |       display: inline-block; | ||||||
|  |       cursor: pointer; | ||||||
|  |       padding-left: 1.25rem; | ||||||
|  |       font-weight: 300; | ||||||
|  |  | ||||||
|  |       &::before { | ||||||
|  |         content: ""; | ||||||
|  |         display: inline-block; | ||||||
|  |         position: absolute; | ||||||
|  |         left: -($radioSize / 4) * 4; | ||||||
|  |         border-radius: 50%; | ||||||
|  |         border: $ui-border-width solid $text-color-70; | ||||||
|  |         width: $radioSize; | ||||||
|  |         height: $radioSize; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &::after { | ||||||
|  |         content: ""; | ||||||
|  |         position: absolute; | ||||||
|  |         display: inline-block; | ||||||
|  |         left: -($radioSize / 4) * 3; | ||||||
|  |         top: $radioSize / 4; | ||||||
|  |         border-radius: 50%; | ||||||
|  |         width: ($radioSize / 4) * 3; | ||||||
|  |         height: ($radioSize / 4) * 3; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &:checked, | ||||||
|  |     &:hover { | ||||||
|  |       + label::after { | ||||||
|  |         background-color: $green; | ||||||
|  |       } | ||||||
|  |       + label::before { | ||||||
|  |         border-color: $text-color; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &:focus { | ||||||
|  |       + label::before { | ||||||
|  |         outline: $ui-border-width solid Highlight; | ||||||
|  |         outline-style: auto; | ||||||
|  |         outline-color: -webkit-focus-ring-color; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -31,7 +31,7 @@ export default { | |||||||
|   font-size: 11px; |   font-size: 11px; | ||||||
|   line-height: 2; |   line-height: 2; | ||||||
|   height: 45px; |   height: 45px; | ||||||
|   letter-spacing: 0.5px; |   letter-spacing: 1.2px; | ||||||
|   padding: 5px 20px 4px 20px; |   padding: 5px 20px 4px 20px; | ||||||
|   margin: 0; |   margin: 0; | ||||||
|   margin-right: 0.3rem; |   margin-right: 0.3rem; | ||||||
|   | |||||||
| @@ -55,6 +55,8 @@ export default { | |||||||
|  |  | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| @import "./src/scss/variables"; | @import "./src/scss/variables"; | ||||||
|  | @import "./src/scss/media-queries"; | ||||||
|  |  | ||||||
| .fade-enter-active { | .fade-enter-active { | ||||||
|   transition: opacity .4s; |   transition: opacity .4s; | ||||||
| } | } | ||||||
| @@ -95,6 +97,20 @@ export default { | |||||||
|     transition: color .5s ease; |     transition: color .5s ease; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   @include mobile-only { | ||||||
|  |     > div { | ||||||
|  |       margin: 6px 6px; | ||||||
|  |       line-height: 1.3rem; | ||||||
|  |     } | ||||||
|  |     h2 { | ||||||
|  |       font-size: 1.1rem; | ||||||
|  |     } | ||||||
|  |     span { | ||||||
|  |       font-size: 0.9rem; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|   .pinstripe { |   .pinstripe { | ||||||
|     height: 100%; |     height: 100%; | ||||||
|     width: 0.5rem; |     width: 0.5rem; | ||||||
|   | |||||||
							
								
								
									
										79
									
								
								src/components/ui/TextArea.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/components/ui/TextArea.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="wrapper"> | ||||||
|  |     <h3 v-if="title" class="title">{{ title }}</h3> | ||||||
|  |     <textarea :placeholder="placeholder" @input="handleInput" v-model="value" :rows="rows" /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   props: { | ||||||
|  |     placeholder: { | ||||||
|  |       type: String, | ||||||
|  |       required: false | ||||||
|  |     }, | ||||||
|  |     title: { | ||||||
|  |       type: String, | ||||||
|  |       required: false | ||||||
|  |     }, | ||||||
|  |     rows: { | ||||||
|  |       type: Number, | ||||||
|  |       required: false, | ||||||
|  |       default: 10 | ||||||
|  |     }, | ||||||
|  |     value: { | ||||||
|  |       type: String, | ||||||
|  |       required: false, | ||||||
|  |       default: undefined | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     handleInput(event) { | ||||||
|  |       if (this.value !== undefined) { | ||||||
|  |         this.$emit('update:value', this.value) | ||||||
|  |       } else { | ||||||
|  |         this.$emit('input', this.value, event) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | @import "./src/scss/variables.scss"; | ||||||
|  |  | ||||||
|  | .wrapper { | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .title { | ||||||
|  |   margin: 0; | ||||||
|  |   font-weight: 400; | ||||||
|  |   text-transform: uppercase; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: $green; | ||||||
|  |   margin-bottom: 0.5rem; | ||||||
|  |   @include tablet-min { | ||||||
|  |     font-size: 16px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | textarea { | ||||||
|  |   width: 100%; | ||||||
|  |   font-size: 14px; | ||||||
|  |   padding: 0.5rem; | ||||||
|  |   border: 2px solid $text-color-50; | ||||||
|  |  | ||||||
|  |   &:focus { | ||||||
|  |     border-color: $text-color; | ||||||
|  |  | ||||||
|  |     outline: none; | ||||||
|  |  | ||||||
|  |     -webkit-box-shadow: none; | ||||||
|  |     -moz-box-shadow: none; | ||||||
|  |     box-shadow: none; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -1,8 +1,10 @@ | |||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <a @click="$emit('click')"><li> |     <a @click="$emit('click')"><li> | ||||||
|       <figure :class="activeClassIfActive"> |       <figure :class="activeClassIfActive" v-if="iconRefNameIfActive"> | ||||||
|         <svg><use :xlink:href="iconRefNameIfActive"/></svg> |         <svg class="icon"> | ||||||
|  |           <use :xlink:href="iconRefNameIfActive"/> | ||||||
|  |         </svg> | ||||||
|       </figure> |       </figure> | ||||||
|  |  | ||||||
|       <span :class="activeClassIfActive">{{ contentTextToDisplay }}</span> |       <span :class="activeClassIfActive">{{ contentTextToDisplay }}</span> | ||||||
| @@ -21,7 +23,7 @@ export default { | |||||||
|   props: { |   props: { | ||||||
|     iconRef: { |     iconRef: { | ||||||
|       type: String, |       type: String, | ||||||
|       required: true |       required: false | ||||||
|     }, |     }, | ||||||
|     iconRefActive: { |     iconRefActive: { | ||||||
|       type: String, |       type: String, | ||||||
| @@ -44,7 +46,7 @@ export default { | |||||||
|     iconRefNameIfActive() { |     iconRefNameIfActive() { | ||||||
|       const { iconRefActive, iconRef, active } = this |       const { iconRefActive, iconRef, active } = this | ||||||
|  |  | ||||||
|       if ((iconRefActive && iconRef) & active) { |       if ((iconRefActive && iconRef) && active) { | ||||||
|         return iconRefActive |         return iconRefActive | ||||||
|       } |       } | ||||||
|       return iconRef |       return iconRef | ||||||
| @@ -98,7 +100,7 @@ li { | |||||||
|     text-align: right; |     text-align: right; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   figure, figure > svg { |   figure, figure > .icon { | ||||||
|     width: 18px; |     width: 18px; | ||||||
|     height: 18px; |     height: 18px; | ||||||
|     margin: 0 7px 0 0; |     margin: 0 7px 0 0; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user