mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: replace nextjs Image element (#1227)
This commit is contained in:
parent
1f3fdd5d0a
commit
684df96969
@ -1,4 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
extends: ["custom"],
|
extends: ["custom"],
|
||||||
|
rules: {
|
||||||
|
"@next/next/no-img-element": "off",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
users: {
|
users: {
|
||||||
avatar: string | null;
|
avatar: string | null;
|
||||||
@ -23,12 +21,10 @@ export const AnalyticsLeaderboard: React.FC<Props> = ({ users, title }) => (
|
|||||||
>
|
>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{user && user.avatar && user.avatar !== "" ? (
|
{user && user.avatar && user.avatar !== "" ? (
|
||||||
<div className="rounded-full h-4 w-4 flex-shrink-0">
|
<div className="relative rounded-full h-4 w-4 flex-shrink-0">
|
||||||
<Image
|
<img
|
||||||
src={user.avatar}
|
src={user.avatar}
|
||||||
height="100%"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-full"
|
||||||
width="100%"
|
|
||||||
className="rounded-full"
|
|
||||||
alt={user.email ?? "None"}
|
alt={user.email ?? "None"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Image from "next/image";
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
// icons
|
// icons
|
||||||
import {
|
import {
|
||||||
@ -22,7 +23,6 @@ import { renderShortNumericDateFormat, timeAgo } from "helpers/date-time.helper"
|
|||||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||||
// types
|
// types
|
||||||
import RemirrorRichTextEditor from "components/rich-text-editor";
|
import RemirrorRichTextEditor from "components/rich-text-editor";
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const activityDetails: {
|
const activityDetails: {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
@ -206,7 +206,7 @@ export const Feeds: React.FC<any> = ({ activities }) => (
|
|||||||
<div className="relative flex items-start space-x-3">
|
<div className="relative flex items-start space-x-3">
|
||||||
<div className="relative px-1">
|
<div className="relative px-1">
|
||||||
{activity.actor_detail.avatar && activity.actor_detail.avatar !== "" ? (
|
{activity.actor_detail.avatar && activity.actor_detail.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={activity.actor_detail.avatar}
|
src={activity.actor_detail.avatar}
|
||||||
alt={activity.actor_detail.first_name}
|
alt={activity.actor_detail.first_name}
|
||||||
height={30}
|
height={30}
|
||||||
@ -276,7 +276,7 @@ export const Feeds: React.FC<any> = ({ activities }) => (
|
|||||||
activityDetails[activity.field as keyof typeof activityDetails]?.icon
|
activityDetails[activity.field as keyof typeof activityDetails]?.icon
|
||||||
) : activity.actor_detail.avatar &&
|
) : activity.actor_detail.avatar &&
|
||||||
activity.actor_detail.avatar !== "" ? (
|
activity.actor_detail.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={activity.actor_detail.avatar}
|
src={activity.actor_detail.avatar}
|
||||||
alt={activity.actor_detail.first_name}
|
alt={activity.actor_detail.first_name}
|
||||||
height={24}
|
height={24}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import React, { useEffect, useState, useRef } from "react";
|
import React, { useEffect, useState, useRef } from "react";
|
||||||
|
|
||||||
// next
|
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
// swr
|
// swr
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
@ -107,12 +104,7 @@ export const ImagePickerPopover: React.FC<Props> = ({ label, value, onChange })
|
|||||||
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
|
||||||
placeholder="Search for images"
|
placeholder="Search for images"
|
||||||
/>
|
/>
|
||||||
<PrimaryButton
|
<PrimaryButton onClick={() => setSearchParams(formData.search)} size="sm">
|
||||||
type="button"
|
|
||||||
onClick={() => setSearchParams(formData.search)}
|
|
||||||
className="bg-indigo-600"
|
|
||||||
size="sm"
|
|
||||||
>
|
|
||||||
Search
|
Search
|
||||||
</PrimaryButton>
|
</PrimaryButton>
|
||||||
</div>
|
</div>
|
||||||
@ -123,12 +115,10 @@ export const ImagePickerPopover: React.FC<Props> = ({ label, value, onChange })
|
|||||||
key={image.id}
|
key={image.id}
|
||||||
className="relative col-span-2 aspect-video md:col-span-1"
|
className="relative col-span-2 aspect-video md:col-span-1"
|
||||||
>
|
>
|
||||||
<Image
|
<img
|
||||||
src={image.urls.small}
|
src={image.urls.small}
|
||||||
alt={image.alt_description}
|
alt={image.alt_description}
|
||||||
layout="fill"
|
className="cursor-pointer rounded absolute top-0 left-0 h-full w-full object-cover"
|
||||||
objectFit="cover"
|
|
||||||
className="cursor-pointer rounded"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
onChange(image.urls.regular);
|
onChange(image.urls.regular);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
@ -301,7 +300,7 @@ export const ActiveCycleDetails: React.FC<TSingleStatProps> = ({ cycle, isComple
|
|||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="flex items-center gap-2.5 text-brand-secondary">
|
<div className="flex items-center gap-2.5 text-brand-secondary">
|
||||||
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={cycle.owned_by.avatar}
|
src={cycle.owned_by.avatar}
|
||||||
height={16}
|
height={16}
|
||||||
width={16}
|
width={16}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
@ -16,8 +15,6 @@ import useLocalStorage from "hooks/use-local-storage";
|
|||||||
import { SingleProgressStats } from "components/core";
|
import { SingleProgressStats } from "components/core";
|
||||||
// ui
|
// ui
|
||||||
import { Avatar } from "components/ui";
|
import { Avatar } from "components/ui";
|
||||||
// icons
|
|
||||||
import User from "public/user.png";
|
|
||||||
// types
|
// types
|
||||||
import { IIssue, IIssueLabels } from "types";
|
import { IIssue, IIssueLabels } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
@ -125,9 +122,9 @@ export const ActiveCycleProgressStats: React.FC<Props> = ({ issues }) => {
|
|||||||
<SingleProgressStats
|
<SingleProgressStats
|
||||||
title={
|
title={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="h-5 w-5 rounded-full border-2 border-white bg-brand-surface-2">
|
<div className="h-5 w-5 rounded-full border-2 border-brand-base bg-brand-surface-2">
|
||||||
<Image
|
<img
|
||||||
src={User}
|
src="/user.png"
|
||||||
height="100%"
|
height="100%"
|
||||||
width="100%"
|
width="100%"
|
||||||
className="rounded-full"
|
className="rounded-full"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
|
|
||||||
@ -454,7 +453,7 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
|
|||||||
|
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={cycle.owned_by.avatar}
|
src={cycle.owned_by.avatar}
|
||||||
height={12}
|
height={12}
|
||||||
width={12}
|
width={12}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
// headless ui
|
// headless ui
|
||||||
@ -246,7 +245,7 @@ export const SingleCycleCard: React.FC<TSingleStatProps> = ({
|
|||||||
<div className="w-16">Creator:</div>
|
<div className="w-16">Creator:</div>
|
||||||
<div className="flex items-center gap-2.5 text-brand-secondary">
|
<div className="flex items-center gap-2.5 text-brand-secondary">
|
||||||
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={cycle.owned_by.avatar}
|
src={cycle.owned_by.avatar}
|
||||||
height={16}
|
height={16}
|
||||||
width={16}
|
width={16}
|
||||||
|
@ -244,7 +244,7 @@ export const SingleCycleList: React.FC<TSingleStatProps> = ({
|
|||||||
|
|
||||||
<div className="flex items-center gap-2.5 text-brand-secondary">
|
<div className="flex items-center gap-2.5 text-brand-secondary">
|
||||||
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={cycle.owned_by.avatar}
|
src={cycle.owned_by.avatar}
|
||||||
height={16}
|
height={16}
|
||||||
width={16}
|
width={16}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
@ -66,11 +65,9 @@ export const SingleUserSelect: React.FC<Props> = ({ collaborator, index, users,
|
|||||||
<div className="grid grid-cols-3 items-center gap-2 rounded-md bg-brand-surface-2 px-2 py-3">
|
<div className="grid grid-cols-3 items-center gap-2 rounded-md bg-brand-surface-2 px-2 py-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="relative h-8 w-8 flex-shrink-0 rounded">
|
<div className="relative h-8 w-8 flex-shrink-0 rounded">
|
||||||
<Image
|
<img
|
||||||
src={collaborator.avatar_url}
|
src={collaborator.avatar_url}
|
||||||
layout="fill"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded"
|
||||||
objectFit="cover"
|
|
||||||
className="rounded"
|
|
||||||
alt={`${collaborator.login} GitHub user`}
|
alt={`${collaborator.login} GitHub user`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Image from "next/image";
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
// icons
|
// icons
|
||||||
@ -346,7 +347,7 @@ export const IssueActivitySection: React.FC<Props> = ({ user }) => {
|
|||||||
?.icon
|
?.icon
|
||||||
) : activityItem.actor_detail.avatar &&
|
) : activityItem.actor_detail.avatar &&
|
||||||
activityItem.actor_detail.avatar !== "" ? (
|
activityItem.actor_detail.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={activityItem.actor_detail.avatar}
|
src={activityItem.actor_detail.avatar}
|
||||||
alt={activityItem.actor_detail.first_name}
|
alt={activityItem.actor_detail.first_name}
|
||||||
height={24}
|
height={24}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
// react-hook-form
|
// react-hook-form
|
||||||
@ -68,12 +67,12 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
<div className="relative flex items-start space-x-3">
|
<div className="relative flex items-start space-x-3">
|
||||||
<div className="relative px-1">
|
<div className="relative px-1">
|
||||||
{comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? (
|
{comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={comment.actor_detail.avatar}
|
src={comment.actor_detail.avatar}
|
||||||
alt={comment.actor_detail.first_name}
|
alt={comment.actor_detail.first_name}
|
||||||
height={30}
|
height={30}
|
||||||
width={30}
|
width={30}
|
||||||
className="grid h-7 w-7 place-items-center rounded-full border-2 border-white bg-gray-500 text-white"
|
className="grid h-7 w-7 place-items-center rounded-full border-2 border-brand-base"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
// headless ui
|
// headless ui
|
||||||
@ -143,7 +141,7 @@ export const Workspace: React.FC<Props> = ({ setStep, setWorkspace, user }) => {
|
|||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
<span className="inline-flex h-10 w-10 items-center justify-center rounded-lg">
|
<span className="inline-flex h-10 w-10 items-center justify-center rounded-lg">
|
||||||
{invitation.workspace.logo && invitation.workspace.logo !== "" ? (
|
{invitation.workspace.logo && invitation.workspace.logo !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={invitation.workspace.logo}
|
src={invitation.workspace.logo}
|
||||||
height="100%"
|
height="100%"
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
@ -186,14 +185,12 @@ export const CreateProjectModal: React.FC<Props> = (props) => {
|
|||||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
>
|
>
|
||||||
<Dialog.Panel className="transform rounded-lg bg-brand-surface-2 text-left shadow-xl transition-all sm:w-full sm:max-w-2xl">
|
<Dialog.Panel className="transform rounded-lg bg-brand-surface-2 text-left shadow-xl transition-all sm:w-full sm:max-w-2xl">
|
||||||
<div className="relative h-36 w-full rounded-t-lg bg-gray-300">
|
<div className="relative h-36 w-full rounded-t-lg bg-brand-surface-2">
|
||||||
{watch("cover_image") !== null && (
|
{watch("cover_image") !== null && (
|
||||||
<Image
|
<img
|
||||||
src={watch("cover_image")!}
|
src={watch("cover_image")!}
|
||||||
layout="fill"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-t-lg"
|
||||||
alt="cover image"
|
alt="Cover Image"
|
||||||
objectFit="cover"
|
|
||||||
className="rounded-t-lg"
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import React from "react";
|
|||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
|
|
||||||
@ -142,15 +141,13 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({
|
|||||||
<Link href={`/${workspaceSlug as string}/projects/${project.id}/issues`}>
|
<Link href={`/${workspaceSlug as string}/projects/${project.id}/issues`}>
|
||||||
<a>
|
<a>
|
||||||
<div className="relative h-32 w-full rounded-t-[10px]">
|
<div className="relative h-32 w-full rounded-t-[10px]">
|
||||||
<Image
|
<img
|
||||||
src={
|
src={
|
||||||
project.cover_image ??
|
project.cover_image ??
|
||||||
"https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
|
"https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
|
||||||
}
|
}
|
||||||
alt={project.name}
|
alt={project.name}
|
||||||
layout="fill"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-t-[10px]"
|
||||||
objectFit="cover"
|
|
||||||
className="rounded-t-[10px]"
|
|
||||||
/>
|
/>
|
||||||
<div className="absolute left-7 bottom-4 flex items-center gap-3 text-white">
|
<div className="absolute left-7 bottom-4 flex items-center gap-3 text-white">
|
||||||
{!hasJoined ? (
|
{!hasJoined ? (
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
@ -62,12 +61,10 @@ const SearchListbox: React.FC<Props> = ({
|
|||||||
if (user.member.avatar && user.member.avatar !== "") {
|
if (user.member.avatar && user.member.avatar !== "") {
|
||||||
return (
|
return (
|
||||||
<div className="relative h-4 w-4">
|
<div className="relative h-4 w-4">
|
||||||
<Image
|
<img
|
||||||
src={user.member.avatar}
|
src={user.member.avatar}
|
||||||
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-full"
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
className="rounded-full"
|
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -151,7 +148,9 @@ const SearchListbox: React.FC<Props> = ({
|
|||||||
</Combobox.Option>
|
</Combobox.Option>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<p className="text-xs text-brand-secondary px-2">No {title.toLowerCase()} found</p>
|
<p className="text-xs text-brand-secondary px-2">
|
||||||
|
No {title.toLowerCase()} found
|
||||||
|
</p>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<p className="text-xs text-brand-secondary px-2">Loading...</p>
|
<p className="text-xs text-brand-secondary px-2">Loading...</p>
|
||||||
|
@ -44,11 +44,9 @@ export const Avatar: React.FC<AvatarProps> = ({
|
|||||||
width: width,
|
width: width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<img
|
||||||
src={user.avatar}
|
src={user.avatar}
|
||||||
height="100%"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-full"
|
||||||
width="100%"
|
|
||||||
className="rounded-full"
|
|
||||||
alt={user.first_name}
|
alt={user.first_name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import { Menu, Transition } from "@headlessui/react";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Image from "next/image";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { CheckIcon, PlusIcon } from "@heroicons/react/24/outline";
|
|
||||||
|
// headless ui
|
||||||
|
import { Menu, Transition } from "@headlessui/react";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "hooks/use-user";
|
import useUser from "hooks/use-user";
|
||||||
import useTheme from "hooks/use-theme";
|
import useTheme from "hooks/use-theme";
|
||||||
@ -14,7 +15,9 @@ import userService from "services/user.service";
|
|||||||
import authenticationService from "services/authentication.service";
|
import authenticationService from "services/authentication.service";
|
||||||
// components
|
// components
|
||||||
import { Avatar, Loader } from "components/ui";
|
import { Avatar, Loader } from "components/ui";
|
||||||
// helper
|
// icons
|
||||||
|
import { CheckIcon, PlusIcon } from "@heroicons/react/24/outline";
|
||||||
|
// helpers
|
||||||
import { truncateText } from "helpers/string.helper";
|
import { truncateText } from "helpers/string.helper";
|
||||||
// types
|
// types
|
||||||
import { IWorkspace } from "types";
|
import { IWorkspace } from "types";
|
||||||
@ -94,12 +97,10 @@ export const WorkspaceSidebarDropdown = () => {
|
|||||||
>
|
>
|
||||||
<div className="relative grid h-6 w-6 place-items-center rounded bg-gray-700 uppercase text-white dark:bg-brand-surface-2 dark:text-gray-800">
|
<div className="relative grid h-6 w-6 place-items-center rounded bg-gray-700 uppercase text-white dark:bg-brand-surface-2 dark:text-gray-800">
|
||||||
{activeWorkspace?.logo && activeWorkspace.logo !== "" ? (
|
{activeWorkspace?.logo && activeWorkspace.logo !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={activeWorkspace.logo}
|
src={activeWorkspace.logo}
|
||||||
|
className="absolute top-0 left-0 h-full w-full object-cover rounded"
|
||||||
alt="Workspace Logo"
|
alt="Workspace Logo"
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
className="rounded"
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
activeWorkspace?.name?.charAt(0) ?? "..."
|
activeWorkspace?.name?.charAt(0) ?? "..."
|
||||||
@ -155,12 +156,10 @@ export const WorkspaceSidebarDropdown = () => {
|
|||||||
<div className="flex items-center justify-start gap-2.5">
|
<div className="flex items-center justify-start gap-2.5">
|
||||||
<span className="relative flex h-6 w-6 items-center justify-center rounded bg-gray-700 p-2 text-xs uppercase text-white">
|
<span className="relative flex h-6 w-6 items-center justify-center rounded bg-gray-700 p-2 text-xs uppercase text-white">
|
||||||
{workspace?.logo && workspace.logo !== "" ? (
|
{workspace?.logo && workspace.logo !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={workspace.logo}
|
src={workspace.logo}
|
||||||
|
className="absolute top-0 left-0 h-full w-full object-cover rounded"
|
||||||
alt="Workspace Logo"
|
alt="Workspace Logo"
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
className="rounded"
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
workspace?.name?.charAt(0) ?? "..."
|
workspace?.name?.charAt(0) ?? "..."
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
// next
|
// helpers
|
||||||
import { getFirstCharacters, truncateText } from "helpers/string.helper";
|
import { getFirstCharacters, truncateText } from "helpers/string.helper";
|
||||||
import Image from "next/image";
|
|
||||||
// react
|
|
||||||
import { useState } from "react";
|
|
||||||
// types
|
// types
|
||||||
import { IWorkspaceMemberInvitation } from "types";
|
import { IWorkspaceMemberInvitation } from "types";
|
||||||
|
|
||||||
@ -16,65 +13,57 @@ const SingleInvitation: React.FC<Props> = ({
|
|||||||
invitation,
|
invitation,
|
||||||
invitationsRespond,
|
invitationsRespond,
|
||||||
handleInvitation,
|
handleInvitation,
|
||||||
}) => {
|
}) => (
|
||||||
const [isChecked, setIsChecked] = useState(invitationsRespond.includes(invitation.id));
|
<li>
|
||||||
|
<label
|
||||||
return (
|
className={`group relative flex cursor-pointer items-start space-x-3 border-2 border-transparent py-4`}
|
||||||
<>
|
htmlFor={invitation.id}
|
||||||
<li>
|
>
|
||||||
<label
|
<div className="flex-shrink-0">
|
||||||
className={`group relative flex cursor-pointer items-start space-x-3 border-2 border-transparent py-4`}
|
<span className="inline-flex h-10 w-10 items-center justify-center rounded-lg">
|
||||||
htmlFor={invitation.id}
|
{invitation.workspace.logo && invitation.workspace.logo !== "" ? (
|
||||||
>
|
<img
|
||||||
<div className="flex-shrink-0">
|
src={invitation.workspace.logo}
|
||||||
<span className="inline-flex h-10 w-10 items-center justify-center rounded-lg">
|
height="100%"
|
||||||
{invitation.workspace.logo && invitation.workspace.logo !== "" ? (
|
width="100%"
|
||||||
<Image
|
className="rounded"
|
||||||
src={invitation.workspace.logo}
|
alt={invitation.workspace.name}
|
||||||
height="100%"
|
/>
|
||||||
width="100%"
|
) : (
|
||||||
className="rounded"
|
<span className="flex h-full w-full items-center justify-center rounded-xl bg-gray-700 p-4 uppercase text-white">
|
||||||
alt={invitation.workspace.name}
|
{getFirstCharacters(invitation.workspace.name)}
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<span className="flex h-full w-full items-center justify-center rounded-xl bg-gray-700 p-4 uppercase text-white">
|
|
||||||
{getFirstCharacters(invitation.workspace.name)}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
)}
|
||||||
<div className="min-w-0 flex-1">
|
</span>
|
||||||
<div className="text-sm font-medium">{truncateText(invitation.workspace.name, 30)}</div>
|
</div>
|
||||||
<p className="text-sm text-brand-secondary">
|
<div className="min-w-0 flex-1">
|
||||||
Invited by{" "}
|
<div className="text-sm font-medium">{truncateText(invitation.workspace.name, 30)}</div>
|
||||||
{invitation.created_by_detail
|
<p className="text-sm text-brand-secondary">
|
||||||
? invitation.created_by_detail.first_name
|
Invited by{" "}
|
||||||
: invitation.workspace.owner.first_name}
|
{invitation.created_by_detail
|
||||||
</p>
|
? invitation.created_by_detail.first_name
|
||||||
</div>
|
: invitation.workspace.owner.first_name}
|
||||||
<div className="flex-shrink-0 self-center">
|
</p>
|
||||||
<button
|
</div>
|
||||||
className={`${
|
<div className="flex-shrink-0 self-center">
|
||||||
invitationsRespond.includes(invitation.id)
|
<button
|
||||||
? "bg-brand-surface-2 text-brand-secondary"
|
className={`${
|
||||||
: "bg-brand-accent text-white"
|
invitationsRespond.includes(invitation.id)
|
||||||
} text-sm px-4 py-2 border border-brand-base rounded-3xl`}
|
? "bg-brand-surface-2 text-brand-secondary"
|
||||||
onClick={(e) => {
|
: "bg-brand-accent text-white"
|
||||||
handleInvitation(
|
} text-sm px-4 py-2 border border-brand-base rounded-3xl`}
|
||||||
invitation,
|
onClick={(e) => {
|
||||||
invitationsRespond.includes(invitation.id) ? "withdraw" : "accepted"
|
handleInvitation(
|
||||||
);
|
invitation,
|
||||||
}}
|
invitationsRespond.includes(invitation.id) ? "withdraw" : "accepted"
|
||||||
>
|
);
|
||||||
{invitationsRespond.includes(invitation.id)
|
}}
|
||||||
? "Invitation Accepted"
|
>
|
||||||
: "Accept Invitation"}
|
{invitationsRespond.includes(invitation.id) ? "Invitation Accepted" : "Accept Invitation"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</>
|
);
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SingleInvitation;
|
export default SingleInvitation;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
// react-hook-form
|
// react-hook-form
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
// services
|
// services
|
||||||
@ -168,14 +166,11 @@ const Profile: NextPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="relative h-12 w-12 overflow-hidden">
|
<div className="relative h-12 w-12 overflow-hidden">
|
||||||
<Image
|
<img
|
||||||
src={watch("avatar")}
|
src={watch("avatar")}
|
||||||
alt={myProfile.first_name}
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-md"
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
className="rounded-md"
|
|
||||||
onClick={() => setIsImageUploadModalOpen(true)}
|
onClick={() => setIsImageUploadModalOpen(true)}
|
||||||
priority
|
alt={myProfile.first_name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
|
|
||||||
@ -138,12 +137,10 @@ const ControlSettings: NextPage = () => {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{person.member.avatar && person.member.avatar !== "" ? (
|
{person.member.avatar && person.member.avatar !== "" ? (
|
||||||
<div className="relative h-4 w-4">
|
<div className="relative h-4 w-4">
|
||||||
<Image
|
<img
|
||||||
src={person.member.avatar}
|
src={person.member.avatar}
|
||||||
alt="avatar"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-full"
|
||||||
className="rounded-full"
|
alt="User Avatar"
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@ -201,12 +198,10 @@ const ControlSettings: NextPage = () => {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{person.member.avatar && person.member.avatar !== "" ? (
|
{person.member.avatar && person.member.avatar !== "" ? (
|
||||||
<div className="relative h-4 w-4">
|
<div className="relative h-4 w-4">
|
||||||
<Image
|
<img
|
||||||
src={person.member.avatar}
|
src={person.member.avatar}
|
||||||
alt="avatar"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-full"
|
||||||
className="rounded-full"
|
alt="User Avatar"
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
@ -256,12 +255,10 @@ const GeneralSettings: NextPage = () => {
|
|||||||
{watch("cover_image") ? (
|
{watch("cover_image") ? (
|
||||||
<div className="h-32 w-full rounded border border-brand-base p-1">
|
<div className="h-32 w-full rounded border border-brand-base p-1">
|
||||||
<div className="relative h-full w-full rounded">
|
<div className="relative h-full w-full rounded">
|
||||||
<Image
|
<img
|
||||||
src={watch("cover_image")!}
|
src={watch("cover_image")!}
|
||||||
|
className="absolute top-0 left-0 h-full w-full object-cover rounded"
|
||||||
alt={projectDetails?.name ?? "Cover image"}
|
alt={projectDetails?.name ?? "Cover image"}
|
||||||
objectFit="cover"
|
|
||||||
layout="fill"
|
|
||||||
className="rounded"
|
|
||||||
/>
|
/>
|
||||||
<div className="absolute bottom-0 flex w-full justify-end">
|
<div className="absolute bottom-0 flex w-full justify-end">
|
||||||
<ImagePickerPopover
|
<ImagePickerPopover
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
@ -177,12 +176,10 @@ const MembersSettings: NextPage = () => {
|
|||||||
<div className="flex items-center gap-x-6 gap-y-2">
|
<div className="flex items-center gap-x-6 gap-y-2">
|
||||||
<div className="relative flex h-10 w-10 items-center justify-center rounded-lg bg-gray-700 p-4 capitalize text-white">
|
<div className="relative flex h-10 w-10 items-center justify-center rounded-lg bg-gray-700 p-4 capitalize text-white">
|
||||||
{member.avatar && member.avatar !== "" ? (
|
{member.avatar && member.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={member.avatar}
|
src={member.avatar}
|
||||||
alt={member.first_name}
|
alt={member.first_name}
|
||||||
layout="fill"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-lg"
|
||||||
objectFit="cover"
|
|
||||||
className="rounded-lg"
|
|
||||||
/>
|
/>
|
||||||
) : member.first_name !== "" ? (
|
) : member.first_name !== "" ? (
|
||||||
member.first_name.charAt(0)
|
member.first_name.charAt(0)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
@ -190,13 +189,10 @@ const WorkspaceSettings: NextPage = () => {
|
|||||||
<button type="button" onClick={() => setIsImageUploadModalOpen(true)}>
|
<button type="button" onClick={() => setIsImageUploadModalOpen(true)}>
|
||||||
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
|
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
|
||||||
<div className="relative mx-auto flex h-12 w-12">
|
<div className="relative mx-auto flex h-12 w-12">
|
||||||
<Image
|
<img
|
||||||
src={watch("logo")!}
|
src={watch("logo")!}
|
||||||
alt="Workspace Logo"
|
alt="Workspace Logo"
|
||||||
objectFit="cover"
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-md"
|
||||||
layout="fill"
|
|
||||||
className="rounded-md"
|
|
||||||
priority
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -177,12 +177,10 @@ const MembersSettings: NextPage = () => {
|
|||||||
<div className="flex items-center gap-x-8 gap-y-2">
|
<div className="flex items-center gap-x-8 gap-y-2">
|
||||||
<div className="relative flex h-10 w-10 items-center justify-center rounded-lg bg-gray-700 p-4 capitalize text-white">
|
<div className="relative flex h-10 w-10 items-center justify-center rounded-lg bg-gray-700 p-4 capitalize text-white">
|
||||||
{member.avatar && member.avatar !== "" ? (
|
{member.avatar && member.avatar !== "" ? (
|
||||||
<Image
|
<img
|
||||||
src={member.avatar}
|
src={member.avatar}
|
||||||
|
className="absolute top-0 left-0 h-full w-full object-cover rounded-lg"
|
||||||
alt={member.first_name}
|
alt={member.first_name}
|
||||||
layout="fill"
|
|
||||||
objectFit="cover"
|
|
||||||
className="rounded-lg"
|
|
||||||
/>
|
/>
|
||||||
) : member.first_name !== "" ? (
|
) : member.first_name !== "" ? (
|
||||||
member.first_name.charAt(0)
|
member.first_name.charAt(0)
|
||||||
|
Loading…
Reference in New Issue
Block a user