mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Client: Tasks and Header v2 (#9168)
* wip: footer * pin bootstrap-vue * compact footer and fixes * compact header * fix member details in other views * fix first party member in header * fix unread notifications badge color * sync + menu fixes * loading bar styles * new filter button * create button * create fixes * quick add * fix quick add inputs * tooltips for create buttons * fix create task moda * fix class badge * fixed footer links * revert change that caused problems with tests and old browsers * misc
This commit is contained in:
@@ -10,66 +10,72 @@
|
||||
.col-12
|
||||
.row.tasks-navigation
|
||||
.col-4.offset-4
|
||||
.input-group
|
||||
.d-flex
|
||||
input.form-control.input-search(type="text", :placeholder="$t('search')", v-model="searchText")
|
||||
.filter-panel(v-if="isFilterPanelOpen", v-on:mouseleave="checkMouseOver")
|
||||
.tags-category.d-flex(
|
||||
v-for="tagsType in tagsByType",
|
||||
v-if="tagsType.tags.length > 0 || tagsType.key === 'tags'",
|
||||
:key="tagsType.key"
|
||||
)
|
||||
.tags-header
|
||||
strong(v-once) {{ $t(tagsType.key) }}
|
||||
a.d-block(v-if="tagsType.key !== 'groups' && !editingTags", @click="editTags(tagsType.key)") {{ $t('editTags2') }}
|
||||
.tags-list.container
|
||||
.row(:class="{'no-gutters': !editingTags}")
|
||||
template(v-if="editingTags && tagsType.key !== 'groups'")
|
||||
.col-6(v-for="(tag, tagIndex) in tagsSnap[tagsType.key]")
|
||||
.inline-edit-input-group.tag-edit-item.input-group
|
||||
input.tag-edit-input.inline-edit-input.form-control(type="text", v-model="tag.name")
|
||||
span.input-group-btn(@click="removeTag(tagIndex, tagsType.key)")
|
||||
.svg-icon.destroy-icon(v-html="icons.destroy")
|
||||
.col-6(v-if="tagsType.key === 'tags'")
|
||||
input.new-tag-item.edit-tag-item.inline-edit-input.form-control(type="text", :placeholder="$t('newTag')", @keydown.enter="addTag($event, tagsType.key)", v-model="newTag")
|
||||
template(v-else)
|
||||
.col-6(v-for="(tag, tagIndex) in tagsType.tags")
|
||||
label.custom-control.custom-checkbox
|
||||
input.custom-control-input(
|
||||
type="checkbox",
|
||||
:checked="isTagSelected(tag)",
|
||||
@change="toggleTag(tag)",
|
||||
)
|
||||
span.custom-control-indicator
|
||||
span.custom-control-description(v-markdown='tag.name')
|
||||
button.btn.btn-secondary.dropdown-toggle.ml-2.d-flex.align-items-center(
|
||||
type="button",
|
||||
@click="toggleFilterPanel()",
|
||||
:class="{active: selectedTags.length > 0}",
|
||||
)
|
||||
.svg-icon.filter-icon.mr-2(v-html="icons.filter")
|
||||
span(v-once) {{ $t('filter') }}
|
||||
.filter-panel(v-if="isFilterPanelOpen", v-on:mouseleave="checkMouseOver")
|
||||
.tags-category.d-flex(
|
||||
v-for="tagsType in tagsByType",
|
||||
v-if="tagsType.tags.length > 0 || tagsType.key === 'tags'",
|
||||
:key="tagsType.key"
|
||||
)
|
||||
.tags-header
|
||||
strong(v-once) {{ $t(tagsType.key) }}
|
||||
a.d-block(v-if="tagsType.key !== 'groups' && !editingTags", @click="editTags(tagsType.key)") {{ $t('editTags2') }}
|
||||
.tags-list.container
|
||||
.row(:class="{'no-gutters': !editingTags}")
|
||||
template(v-if="editingTags && tagsType.key !== 'groups'")
|
||||
.col-6(v-for="(tag, tagIndex) in tagsSnap[tagsType.key]")
|
||||
.inline-edit-input-group.tag-edit-item.input-group
|
||||
input.tag-edit-input.inline-edit-input.form-control(type="text", v-model="tag.name")
|
||||
span.input-group-btn(@click="removeTag(tagIndex, tagsType.key)")
|
||||
.svg-icon.destroy-icon(v-html="icons.destroy")
|
||||
.col-6(v-if="tagsType.key === 'tags'")
|
||||
input.new-tag-item.edit-tag-item.inline-edit-input.form-control(type="text", :placeholder="$t('newTag')", @keydown.enter="addTag($event, tagsType.key)", v-model="newTag")
|
||||
template(v-else)
|
||||
.col-6(v-for="(tag, tagIndex) in tagsType.tags")
|
||||
label.custom-control.custom-checkbox
|
||||
input.custom-control-input(
|
||||
type="checkbox",
|
||||
:checked="isTagSelected(tag)",
|
||||
@change="toggleTag(tag)",
|
||||
)
|
||||
span.custom-control-indicator
|
||||
span.custom-control-description(v-markdown='tag.name')
|
||||
|
||||
.filter-panel-footer.clearfix
|
||||
template(v-if="editingTags === true")
|
||||
.text-center
|
||||
a.mr-3.btn-filters-primary(@click="saveTags()", v-once) {{ $t('saveEdits') }}
|
||||
a.btn-filters-secondary(@click="cancelTagsEditing()", v-once) {{ $t('cancel') }}
|
||||
template(v-else)
|
||||
.float-left
|
||||
a.btn-filters-danger(@click="resetFilters()", v-once) {{ $t('resetFilters') }}
|
||||
.float-right
|
||||
a.btn-filters-secondary(@click="closeFilterPanel()", v-once) {{ $t('cancel') }}
|
||||
span.input-group-btn
|
||||
button.btn.btn-secondary.filter-button(
|
||||
type="button",
|
||||
@click="toggleFilterPanel()",
|
||||
:class="{'filter-button-open': selectedTags.length > 0}",
|
||||
.filter-panel-footer.clearfix
|
||||
template(v-if="editingTags === true")
|
||||
.text-center
|
||||
a.mr-3.btn-filters-primary(@click="saveTags()", v-once) {{ $t('saveEdits') }}
|
||||
a.btn-filters-secondary(@click="cancelTagsEditing()", v-once) {{ $t('cancel') }}
|
||||
template(v-else)
|
||||
.float-left
|
||||
a.btn-filters-danger(@click="resetFilters()", v-once) {{ $t('resetFilters') }}
|
||||
.float-right
|
||||
a.btn-filters-secondary(@click="closeFilterPanel()", v-once) {{ $t('cancel') }}
|
||||
.create-task-area.d-flex
|
||||
transition(name="slide-tasks-btns")
|
||||
.d-flex(v-if="openCreateBtn")
|
||||
.create-task-btn.rounded-btn(
|
||||
v-for="type in columns",
|
||||
:key="type",
|
||||
@click="createTask(type)",
|
||||
v-b-tooltip.hover.bottom="$t(type)",
|
||||
)
|
||||
.d-flex.align-items-center
|
||||
span(v-once) {{ $t('filter') }}
|
||||
.svg-icon.filter-icon(v-html="icons.filter")
|
||||
#create-dropdown.col-1.offset-3
|
||||
b-dropdown(:right="true", :variant="'success'")
|
||||
div(slot="button-content")
|
||||
.svg-icon.positive(v-html="icons.positive")
|
||||
| {{ $t('addTaskToUser') }}
|
||||
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
|
||||
span.dropdown-icon-item(v-once)
|
||||
span.svg-icon.inline(v-html="icons[type]", :class='`icon_${type}`')
|
||||
span.text {{$t(type)}}
|
||||
.svg-icon(v-html="icons[type]", :class='`icon-${type}`')
|
||||
|
||||
#create-task-btn.create-btn.rounded-btn.btn.btn-success(
|
||||
@click="openCreateBtn = !openCreateBtn",
|
||||
:class="{open: openCreateBtn}",
|
||||
)
|
||||
.svg-icon(v-html="icons.positive")
|
||||
b-tooltip(target="create-task-btn", placement="bottom", v-if="!openCreateBtn") {{ $t('addTaskToUser') }}
|
||||
|
||||
.row.tasks-columns
|
||||
task-column.col-lg-3.col-md-6(
|
||||
@@ -84,86 +90,101 @@
|
||||
spells
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#create-dropdown .dropdown-toggle::after {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.user-tasks-page {
|
||||
padding-top: 31px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.tasks-navigation {
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.positive {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
color: $green-500;
|
||||
margin-right: 8px;
|
||||
padding-top: 6px;
|
||||
.create-task-area {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
top: -40px;
|
||||
z-index: 999;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.dropdown-icon-item .svg-icon {
|
||||
color: #C3C0C7;
|
||||
.slide-tasks-btns-leave-active, .slide-tasks-btns-enter-active {
|
||||
max-width: 240px;
|
||||
overflow-x: hidden;
|
||||
transition: all 0.3s cubic-bezier(0, 1, 0.5, 1);
|
||||
}
|
||||
.slide-tasks-btns-enter, .slide-tasks-btns-leave-to {
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.dropdown-icon-item {
|
||||
.icon_habit {
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
.rounded-btn {
|
||||
margin-left: 8px;
|
||||
background: $white;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 100px;
|
||||
box-shadow: 0 2px 2px 0 rgba($black, 0.16), 0 1px 4px 0 rgba($black, 0.12);
|
||||
cursor: pointer;
|
||||
color: $gray-200;
|
||||
|
||||
&:hover:not(.create-btn) {
|
||||
color: $purple-400;
|
||||
box-shadow: 0 1px 8px 0 rgba($black, 0.12), 0 4px 4px 0 rgba($black, 0.16);
|
||||
}
|
||||
|
||||
.icon_daily {
|
||||
width: 24px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.icon_todo {
|
||||
.svg-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.icon_reward {
|
||||
width: 26px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
&.icon-habit {
|
||||
width: 24px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.dropdown-icon-item:hover .svg-icon, .dropdown-item.active .svg-icon {
|
||||
color: #4f2a93;
|
||||
}
|
||||
&.icon-daily {
|
||||
width: 21.6px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
button.btn.btn-secondary.filter-button {
|
||||
box-shadow: none;
|
||||
border-radius: 2px;
|
||||
border: 1px solid $gray-400 !important;
|
||||
&.icon-todo {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
&:hover, &:active, &:focus, &.open {
|
||||
box-shadow: none;
|
||||
border-color: $purple-500 !important;
|
||||
color: $gray-50 !important;
|
||||
}
|
||||
|
||||
&.filter-button-open {
|
||||
color: $purple-200 !important;
|
||||
|
||||
.filter-icon {
|
||||
color: $purple-200 !important;
|
||||
&.icon-reward {
|
||||
width: 23.4px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-icon {
|
||||
height: 10px;
|
||||
width: 12px;
|
||||
color: $gray-50;
|
||||
margin-left: 15px;
|
||||
.create-btn {
|
||||
color: $white;
|
||||
background-color: $green-10;
|
||||
|
||||
.svg-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
transition: transform 0.3s cubic-bezier(0, 1, 0.5, 1);
|
||||
}
|
||||
|
||||
&.open {
|
||||
background: $gray-200 !important;
|
||||
|
||||
.svg-icon {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.filter-panel {
|
||||
@@ -285,6 +306,9 @@ import rewardIcon from 'assets/svg/reward.svg';
|
||||
import uuid from 'uuid';
|
||||
import Vue from 'vue';
|
||||
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
|
||||
import bTooltip from 'bootstrap-vue/lib/directives/tooltip';
|
||||
import bTooltipComponent from 'bootstrap-vue/lib/components/tooltip';
|
||||
|
||||
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
|
||||
import throttle from 'lodash/throttle';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
@@ -300,12 +324,14 @@ export default {
|
||||
TaskModal,
|
||||
bDropdown,
|
||||
bDropdownItem,
|
||||
bTooltip: bTooltipComponent,
|
||||
Item,
|
||||
spells,
|
||||
brokenTaskModal,
|
||||
},
|
||||
directives: {
|
||||
markdown,
|
||||
bTooltip,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -313,6 +339,7 @@ export default {
|
||||
searchText: null,
|
||||
searchTextThrottled: null,
|
||||
isFilterPanelOpen: false,
|
||||
openCreateBtn: false,
|
||||
icons: Object.freeze({
|
||||
positive: positiveIcon,
|
||||
filter: filterIcon,
|
||||
@@ -415,6 +442,7 @@ export default {
|
||||
});
|
||||
},
|
||||
createTask (type) {
|
||||
this.openCreateBtn = false;
|
||||
this.creatingTask = taskDefaults({type, text: ''});
|
||||
this.creatingTask.tags = this.selectedTags;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user