Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: select component integration #285

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 67 additions & 7 deletions codex-ui/dev/pages/components/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,73 @@
Component of the form that allows you to select one or more options from the list (currently one)
</template>
</PageHeader>
<Select
:items="options"
:default-item="defaultItem"
/>
<div class="ex">
Default
<Select
v-model="currentItem"
:align="{vertically: 'below', horizontally: 'left'}"
:is-disabled="false"
:items="options"
/>
Disabled
<Select
v-model="currentItem"
:align="{vertically: 'below', horizontally: 'left'}"
:is-disabled="true"
:items="options"
/>
</div>
<Heading :level="2">
Getting selected option
</Heading>
Selected option replaces default value and can be easily got from the same object:
<div class="ex">
<i>{{ currentItem }}</i>
</div>
<Heading
:level="2"
>
Aligning
</Heading>
You can choose vertical aligning from <code>below</code> and <code>above</code> and horizontal aligning from <code>left</code> and <code>right</code>
<div class="ex">
<Select
v-model="currentItem"
:align="{vertically: 'below', horizontally: 'left'}"
:is-disabled="false"
:items="options"
/>
<Select
v-model="currentItem"
:align="{vertically: 'below', horizontally: 'right'}"
:is-disabled="false"
:items="options"
/>
<Select
v-model="currentItem"
:align="{vertically: 'above', horizontally: 'left'}"
:is-disabled="false"
:items="options"
/>
<Select
v-model="currentItem"
:align="{vertically: 'above', horizontally: 'right'}"
:is-disabled="false"
:items="options"
/>
</div>
</template>

<script setup lang="ts">
import PageHeader from '../../components/PageHeader.vue';
import { ContextMenuItem, DefaultItem, Select } from '../../../src';
import { ContextMenuItem, Heading, Select } from '../../../src';
import { ref } from 'vue';

const defaultItem: DefaultItem = {
const currentItem = ref({
title: 'Choose an option',
onActivate: () => {},
};
});

const options: ContextMenuItem[] = [
{
type: 'default',
Expand Down Expand Up @@ -50,4 +103,11 @@ const options: ContextMenuItem[] = [
</script>

<style scoped>
.ex {
display: grid;
gap: var(--spacing-xl);
margin: var(--spacing-xl) 0 var(--spacing-xxl);
grid-template-columns: repeat(2, max-content);
align-items: center;
}
</style>
10 changes: 6 additions & 4 deletions codex-ui/src/vue/components/popover/Popover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
v-show="isOpen"
ref="popoverEl"
:class="$style.popover"
:style="{
left: position.left + 'px',
top: position.top + 'px',
transform: position.transform,
width: width + 'px' // Assuming width is in pixels
}"
>
<component
:is="content.component"
Expand Down Expand Up @@ -51,10 +57,6 @@ onClickOutside(popoverEl, hide, {
border-radius: var(--radius-field);
border: 1px solid var(--base--border);
padding: var(--h-padding);
left: v-bind('position.left');
top: v-bind('position.top');
transform: v-bind('position.transform');
width: v-bind('width');
box-sizing: border-box;
}
</style>
22 changes: 12 additions & 10 deletions codex-ui/src/vue/components/select/Select.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
<template>
<Button
:icon="activeItem.icon"
:icon="currentItem.icon"
:disabled="isDisabled"
trailing-icon="BracketsVertical"
secondary
@click="togglePopover($event.currentTarget, {vertically: 'below', horizontally: 'left'})"
@click="togglePopover($event.currentTarget)"
>
{{ activeItem.title }}
{{ currentItem.title }}
</Button>
</template>
<script setup lang="ts">
import type { ContextMenuItem as SelectItem, DefaultItem } from '../context-menu/ContextMenu.types';
import { ContextMenu } from '../context-menu';
import { onMounted, ref } from 'vue';
import { onMounted } from 'vue';
import { usePopover, PopoverShowParams } from '../popover';
import { Button } from '../button';

const props = defineProps<{
align: PopoverShowParams['align'];
isDisabled: boolean;
items: SelectItem[];
defaultItem: DefaultItem;
}>();

const align = props.align;
const items = props.items;
const { showPopover, hide, isOpen } = usePopover();

const togglePopover = (el: HTMLElement, align: PopoverShowParams['align']) => {
if (!isOpen.value) {
const togglePopover = (el: HTMLElement) => {
if (!isOpen.value && !props.isDisabled) {
showPopover({
targetEl: el,
with: {
Expand All @@ -41,12 +44,11 @@ const togglePopover = (el: HTMLElement, align: PopoverShowParams['align']) => {
};

/* Default item value for select on page load */
const defaultValue: SelectItem = props.defaultItem;
const activeItem = ref(defaultValue);
const currentItem = defineModel<DefaultItem>({ required: true });

/* Main function to update selected item */
const updateActiveItem = (item: DefaultItem) => {
activeItem.value = item;
currentItem.value = item;
hide();
};

Expand Down
70 changes: 43 additions & 27 deletions src/presentation/components/team/RoleSelect.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
<template>
<div v-if="teamMember.user.id != user?.id">
<select
<div>
<Select
v-model="selectedRole"
@change="updateMemberRole"
>
<option
v-for="(role, index) in roleOptions"
:key="index"
:value="role"
>
{{ t(`noteSettings.team.roles.${role}`) }}
</option>
</select>
:align="{ vertically: 'below', horizontally: 'right' }"
:is-disabled="teamMember.user.id == user?.id || isCreator"
:items="roleItems"
/>
</div>
</template>

<script setup lang="ts">
import { MemberRole, TeamMember } from '@/domain/entities/Team.ts';
import { NoteId } from '@/domain/entities/Note.ts';
import { computed, ref } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import useNoteSettings from '@/application/services/useNoteSettings.ts';
import { useAppState } from '@/application/services/useAppState';
import { useI18n } from 'vue-i18n';
import { ContextMenuItem, DefaultItem, Select } from 'codex-ui/vue';

/**
* TeamMember props
Expand All @@ -37,31 +31,53 @@ const props = defineProps<{
noteId: NoteId;
}>();

const selectedRole = ref(MemberRole[props.teamMember.role]);
/* property to disable select for changing creator's role */
let isCreator = false;

const selectedRole = ref<DefaultItem>({
title: MemberRole[props.teamMember.role],
onActivate: () => {},
});

const roleOptions = computed(() => Object.values(MemberRole).filter(value => typeof value === 'string'));
const roleItems: ContextMenuItem[] = [];

const { changeRole } = useNoteSettings();
roleOptions.value.forEach((role) => {
roleItems.push({
title: role.toString(),
onActivate: () => {},
});
});

const { changeRole } = useNoteSettings();
const { user } = useAppState();

const { t } = useI18n();
/* Watch role's update */
watch(selectedRole, (newRole, oldRole) => {
if (newRole.title !== oldRole.title) {
updateMemberRole(newRole.title);
}
});

/**
* Updates the user role if it has been changed
*
* @param updatedRole - new role needed to set
*/
async function updateMemberRole() {
changeRole(props.noteId, props.teamMember.user.id, MemberRole[selectedRole.value as keyof typeof MemberRole]);
async function updateMemberRole(updatedRole: string | any) {
changeRole(props.noteId, props.teamMember.user.id, MemberRole[updatedRole as keyof typeof MemberRole]).catch(() => {
selectedRole.value = {
title: 'Write',
onActivate: () => {},
};
isCreator = true;
});
}
/* Check, is the user creator or not to disable select on true */
onMounted(() => {
updateMemberRole(MemberRole[props.teamMember.role]);
});
</script>

<style scoped>
.member {
margin-top: var(--spacing-l);
}
.member-name {
display: flex;
align-items: center;
gap: var(--spacing-very-x);
}
</style>
1 change: 1 addition & 0 deletions src/presentation/components/team/Team.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:key="member.id"
:title="member.user.name || member.user.email"
:has-delimiter="memberIndex !== team.length - 1"
data-dimensions="medium"
>
<template #right>
<RoleSelect
Expand Down
Loading