first commit
This commit is contained in:
82
services/web/frontend/js/features/project-list/util/api.ts
Normal file
82
services/web/frontend/js/features/project-list/util/api.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Tag } from '../../../../../app/src/Features/Tags/types'
|
||||
import {
|
||||
GetProjectsResponseBody,
|
||||
Sort,
|
||||
} from '../../../../../types/project/dashboard/api'
|
||||
import { deleteJSON, postJSON } from '../../../infrastructure/fetch-json'
|
||||
|
||||
export function getProjects(sortBy: Sort): Promise<GetProjectsResponseBody> {
|
||||
return postJSON('/api/project', { body: { sort: sortBy } })
|
||||
}
|
||||
|
||||
export function createTag(name: string, color?: string): Promise<Tag> {
|
||||
return postJSON(`/tag`, {
|
||||
body: { name, color },
|
||||
})
|
||||
}
|
||||
|
||||
export function editTag(
|
||||
tagId: string,
|
||||
newTagName: string,
|
||||
newTagColor?: string
|
||||
) {
|
||||
return postJSON(`/tag/${tagId}/edit`, {
|
||||
body: { name: newTagName, color: newTagColor },
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteTag(tagId: string) {
|
||||
return deleteJSON(`/tag/${tagId}`)
|
||||
}
|
||||
|
||||
export function addProjectsToTag(tagId: string, projectIds: string[]) {
|
||||
return postJSON(`/tag/${tagId}/projects`, {
|
||||
body: {
|
||||
projectIds,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function removeProjectFromTag(tagId: string, projectId: string) {
|
||||
return deleteJSON(`/tag/${tagId}/project/${projectId}`)
|
||||
}
|
||||
|
||||
export function removeProjectsFromTag(tagId: string, projectIds: string[]) {
|
||||
return postJSON(`/tag/${tagId}/projects/remove`, {
|
||||
body: {
|
||||
projectIds,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function archiveProject(projectId: string) {
|
||||
return postJSON(`/project/${projectId}/archive`)
|
||||
}
|
||||
|
||||
export function deleteProject(projectId: string) {
|
||||
return deleteJSON(`/project/${projectId}`)
|
||||
}
|
||||
|
||||
export function leaveProject(projectId: string) {
|
||||
return postJSON(`/project/${projectId}/leave`)
|
||||
}
|
||||
|
||||
export function renameProject(projectId: string, newName: string) {
|
||||
return postJSON(`/project/${projectId}/rename`, {
|
||||
body: {
|
||||
newProjectName: newName,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function trashProject(projectId: string) {
|
||||
return postJSON(`/project/${projectId}/trash`)
|
||||
}
|
||||
|
||||
export function unarchiveProject(projectId: string) {
|
||||
return deleteJSON(`/project/${projectId}/archive`)
|
||||
}
|
||||
|
||||
export function untrashProject(projectId: string) {
|
||||
return deleteJSON(`/project/${projectId}/trash`)
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
import { getUserName } from './user'
|
||||
import { Project } from '../../../../../types/project/dashboard/api'
|
||||
|
||||
export function getOwnerName(project: Project) {
|
||||
if (project.accessLevel === 'owner') {
|
||||
return 'You'
|
||||
}
|
||||
|
||||
if (project.owner != null) {
|
||||
return getUserName(project.owner)
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export function isDeletableProject(project: Project) {
|
||||
return project.accessLevel === 'owner' && project.trashed
|
||||
}
|
||||
|
||||
export function isLeavableProject(project: Project) {
|
||||
return project.accessLevel !== 'owner' && project.trashed
|
||||
}
|
||||
|
||||
export function isArchivedOrTrashed(project: Project) {
|
||||
return project.archived || project.trashed
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
import { Project, Sort } from '../../../../../types/project/dashboard/api'
|
||||
import { SortingOrder } from '../../../../../types/sorting-order'
|
||||
import { getOwnerName } from './project'
|
||||
import { Compare } from '../../../../../types/helpers/array/sort'
|
||||
|
||||
const order = (order: SortingOrder, projects: Project[]) => {
|
||||
return order === 'asc' ? [...projects] : projects.reverse()
|
||||
}
|
||||
|
||||
export const ownerNameComparator = (v1: Project, v2: Project) => {
|
||||
const ownerNameV1 = getOwnerName(v1)
|
||||
const ownerNameV2 = getOwnerName(v2)
|
||||
|
||||
// sorting by owner === 'You' is with highest precedence
|
||||
if (ownerNameV1 === 'You') {
|
||||
if (ownerNameV2 === 'You') {
|
||||
return v1.lastUpdated < v2.lastUpdated
|
||||
? Compare.SORT_A_BEFORE_B
|
||||
: Compare.SORT_A_AFTER_B
|
||||
}
|
||||
|
||||
return Compare.SORT_A_AFTER_B
|
||||
}
|
||||
|
||||
// empty owner name
|
||||
if (ownerNameV1 === '') {
|
||||
if (ownerNameV2 === '') {
|
||||
return v1.lastUpdated < v2.lastUpdated
|
||||
? Compare.SORT_A_BEFORE_B
|
||||
: Compare.SORT_A_AFTER_B
|
||||
}
|
||||
|
||||
return Compare.SORT_A_BEFORE_B
|
||||
}
|
||||
|
||||
if (ownerNameV2 === 'You') {
|
||||
return Compare.SORT_A_BEFORE_B
|
||||
}
|
||||
|
||||
if (ownerNameV2 === '') {
|
||||
return Compare.SORT_A_AFTER_B
|
||||
}
|
||||
|
||||
if (v1.source === 'token') {
|
||||
return Compare.SORT_A_BEFORE_B
|
||||
}
|
||||
|
||||
if (v2.source === 'token') {
|
||||
return Compare.SORT_A_AFTER_B
|
||||
}
|
||||
|
||||
return ownerNameV1.localeCompare(ownerNameV2)
|
||||
}
|
||||
|
||||
export const defaultComparator = (
|
||||
v1: Project,
|
||||
v2: Project,
|
||||
key: 'name' | 'lastUpdated'
|
||||
) => {
|
||||
const value1 = v1[key].toLowerCase()
|
||||
const value2 = v2[key].toLowerCase()
|
||||
|
||||
if (value1 !== value2) {
|
||||
return value1 < value2 ? Compare.SORT_A_BEFORE_B : Compare.SORT_A_AFTER_B
|
||||
}
|
||||
|
||||
return Compare.SORT_KEEP_ORDER
|
||||
}
|
||||
|
||||
export default function sortProjects(projects: Project[], sort: Sort) {
|
||||
let sorted = [...projects]
|
||||
if (sort.by === 'title') {
|
||||
sorted = sorted.sort((...args) => {
|
||||
return defaultComparator(...args, 'name')
|
||||
})
|
||||
}
|
||||
|
||||
if (sort.by === 'lastUpdated') {
|
||||
sorted = sorted.sort((...args) => {
|
||||
return defaultComparator(...args, 'lastUpdated')
|
||||
})
|
||||
}
|
||||
|
||||
if (sort.by === 'owner') {
|
||||
sorted = sorted.sort((...args) => {
|
||||
return ownerNameComparator(...args)
|
||||
})
|
||||
}
|
||||
|
||||
return order(sort.order, sorted)
|
||||
}
|
11
services/web/frontend/js/features/project-list/util/tag.ts
Normal file
11
services/web/frontend/js/features/project-list/util/tag.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Tag } from '../../../../../app/src/Features/Tags/types'
|
||||
import { getHueForId } from '@/shared/utils/colors'
|
||||
|
||||
export const MAX_TAG_LENGTH = 50
|
||||
|
||||
export function getTagColor(tag?: Tag): string | undefined {
|
||||
if (!tag) {
|
||||
return undefined
|
||||
}
|
||||
return tag.color || `hsl(${getHueForId(tag._id)}, 70%, 45%)`
|
||||
}
|
22
services/web/frontend/js/features/project-list/util/user.ts
Normal file
22
services/web/frontend/js/features/project-list/util/user.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { UserRef } from '../../../../../types/project/dashboard/api'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
export function getUserName(user: UserRef) {
|
||||
if (user?.id === getMeta('ol-user_id')) {
|
||||
return 'You'
|
||||
}
|
||||
|
||||
if (user) {
|
||||
const { firstName, lastName, email } = user
|
||||
|
||||
if (firstName || lastName) {
|
||||
return [firstName, lastName].filter(n => n != null).join(' ')
|
||||
}
|
||||
|
||||
if (email) {
|
||||
return email
|
||||
}
|
||||
}
|
||||
|
||||
return 'None'
|
||||
}
|
Reference in New Issue
Block a user