show icons on cards during indeterminate and fully selected states

This commit is contained in:
undergroundwires
2020-09-17 21:46:20 +01:00
parent 07fc555324
commit 1072505219
10 changed files with 200 additions and 18 deletions

View File

@@ -6,7 +6,8 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
/** REGULAR ICONS (PREFIX: far) */
import { faFolderOpen, faFolder, faSmile } from '@fortawesome/free-regular-svg-icons';
/** SOLID ICONS (PREFIX: fas (default)) */
import { faTimes, faFileDownload, faCopy, faSearch, faInfoCircle, faUserSecret, faDesktop, faTag, faGlobe, faSave } from '@fortawesome/free-solid-svg-icons';
import { faTimes, faFileDownload, faCopy, faSearch, faInfoCircle, faUserSecret, faDesktop,
faTag, faGlobe, faSave, faBatteryFull, faBatteryHalf } from '@fortawesome/free-solid-svg-icons';
export class IconBootstrapper implements IVueBootstrapper {
@@ -24,6 +25,7 @@ export class IconBootstrapper implements IVueBootstrapper {
faFileDownload, faSave,
faCopy,
faSearch,
faBatteryFull, faBatteryHalf,
faInfoCircle);
vue.component('font-awesome-icon', FontAwesomeIcon);
}

View File

@@ -8,9 +8,17 @@
}"
ref="cardElement">
<div class="card__inner">
<span v-if="cardTitle && cardTitle.length > 0">{{cardTitle}}</span>
<span v-if="cardTitle && cardTitle.length > 0">
<span>{{cardTitle}}</span>
</span>
<span v-else>Oh no 😢</span>
<!-- Expand icon -->
<font-awesome-icon :icon="['far', isExpanded ? 'folder-open' : 'folder']" class="card__inner__expand-icon" />
<!-- Indeterminate and full states -->
<div class="card__inner__state-icons">
<font-awesome-icon v-if="isAnyChildSelected && !areAllChildrenSelected" :icon="['fa', 'battery-half']" />
<font-awesome-icon v-if="areAllChildrenSelected" :icon="['fa', 'battery-full']" />
</div>
</div>
<div class="card__expander" v-on:click.stop>
<div class="card__expander__content">
@@ -27,6 +35,8 @@
import { Component, Prop, Watch, Emit } from 'vue-property-decorator';
import ScriptsTree from '@/presentation/Scripts/ScriptsTree/ScriptsTree.vue';
import { StatefulVue } from '@/presentation/StatefulVue';
import { ICategory } from '@/domain/ICategory';
import { IUserSelection } from '@/application/State/IApplicationState';
@Component({
components: {
@@ -36,17 +46,21 @@ import { StatefulVue } from '@/presentation/StatefulVue';
export default class CardListItem extends StatefulVue {
@Prop() public categoryId!: number;
@Prop() public activeCategoryId!: number;
public cardTitle?: string = '';
public isExpanded: boolean = false;
public cardTitle = '';
public isExpanded = false;
public isAnyChildSelected = false;
public areAllChildrenSelected = false;
@Emit('selected')
@Emit('selected')
public onSelected(isExpanded: boolean) {
this.isExpanded = isExpanded;
}
@Watch('activeCategoryId')
public async onActiveCategoryChanged(value: |number) {
this.isExpanded = value === this.categoryId;
}
@Watch('isExpanded')
public async onExpansionChangedAsync(newValue: number, oldValue: number) {
if (!oldValue && newValue) {
@@ -57,20 +71,23 @@ export default class CardListItem extends StatefulVue {
}
public async mounted() {
this.cardTitle = this.categoryId ? await this.getCardTitleAsync(this.categoryId) : undefined;
const state = await this.getCurrentStateAsync();
state.selection.changed.on(() => {
this.updateStateAsync(this.categoryId);
});
this.updateStateAsync(this.categoryId);
}
@Watch('categoryId')
public async onCategoryIdChanged(value: |number) {
this.cardTitle = value ? await this.getCardTitleAsync(value) : undefined;
}
private async getCardTitleAsync(categoryId: number): Promise<string | undefined> {
const state = await this.getCurrentStateAsync();
const category = state.app.findCategory(this.categoryId);
return category ? category.name : undefined;
public async updateStateAsync(value: |number) {
const state = await this.getCurrentStateAsync();
const category = !value ? undefined : state.app.findCategory(this.categoryId);
this.cardTitle = category ? category.name : undefined;
this.isAnyChildSelected = category ? state.selection.isAnySelected(category) : false;
this.areAllChildrenSelected = category ? state.selection.areAllSelected(category) : false;
}
}
</script>
<style scoped lang="scss">
@@ -93,7 +110,7 @@ $expanded-margin-top: 30px;
@media screen and (max-width: $small-screen-width) { width: 90%; }
&__inner {
padding: $card-padding;
padding: $card-padding $card-padding 0 $card-padding;
position: relative;
cursor: pointer;
background-color: $gray;
@@ -115,13 +132,21 @@ $expanded-margin-top: 30px;
&:after {
transition: all 0.3s ease-in-out;
}
&__state-icons {
height: $card-padding;
margin-right: -$card-padding;
padding-right: 10px;
display: flex;
justify-content: flex-end;
}
&__expand-icon {
width: 100%;
margin-top: .25em;
vertical-align: middle;
}
}
&__expander {
transition: all 0.2s ease-in-out;
position: relative;

View File

@@ -45,7 +45,7 @@
import { Component } from 'vue-property-decorator';
import { StatefulVue } from '@/presentation/StatefulVue';
import SelectableOption from './SelectableOption.vue';
import { IApplicationState, IUserSelection } from '@/application/State/IApplicationState';
import { IApplicationState } from '@/application/State/IApplicationState';
import { IScript } from '@/domain/IScript';
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
import { RecommendationLevel } from '@/domain/RecommendationLevel';