You've already forked AstralRinth
forked from didirus/AstralRinth
Add TailwindCSS (#1252)
* Setup TailwindCSS * Fully setup configuration * Refactor some tailwind variables
This commit is contained in:
@@ -15,9 +15,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ChartDisplay from '~/components/ui/charts/ChartDisplay.vue'
|
||||
import ChartDisplay from "~/components/ui/charts/ChartDisplay.vue";
|
||||
|
||||
const { projects } = inject('organizationContext')
|
||||
const { projects } = inject("organizationContext");
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { Button, FileInput, Avatar, ConfirmModal } from '@modrinth/ui'
|
||||
import { UploadIcon, SaveIcon, TrashIcon } from '@modrinth/assets'
|
||||
import { Button, FileInput, Avatar, ConfirmModal } from "@modrinth/ui";
|
||||
import { UploadIcon, SaveIcon, TrashIcon } from "@modrinth/assets";
|
||||
|
||||
const {
|
||||
organization,
|
||||
@@ -9,93 +9,93 @@ const {
|
||||
deleteIcon,
|
||||
patchIcon,
|
||||
patchOrganization,
|
||||
} = inject('organizationContext')
|
||||
} = inject("organizationContext");
|
||||
|
||||
const icon = ref(null)
|
||||
const deletedIcon = ref(false)
|
||||
const previewImage = ref(null)
|
||||
const icon = ref(null);
|
||||
const deletedIcon = ref(false);
|
||||
const previewImage = ref(null);
|
||||
|
||||
const name = ref(organization.value.name)
|
||||
const slug = ref(organization.value.slug)
|
||||
const name = ref(organization.value.name);
|
||||
const slug = ref(organization.value.slug);
|
||||
|
||||
const summary = ref(organization.value.description)
|
||||
const summary = ref(organization.value.description);
|
||||
|
||||
const patchData = computed(() => {
|
||||
const data = {}
|
||||
const data = {};
|
||||
if (name.value !== organization.value.name) {
|
||||
data.name = name.value
|
||||
data.name = name.value;
|
||||
}
|
||||
if (slug.value !== organization.value.slug) {
|
||||
data.slug = slug.value
|
||||
data.slug = slug.value;
|
||||
}
|
||||
if (summary.value !== organization.value.description) {
|
||||
data.description = summary.value
|
||||
data.description = summary.value;
|
||||
}
|
||||
return data
|
||||
})
|
||||
return data;
|
||||
});
|
||||
|
||||
const hasChanges = computed(() => {
|
||||
return Object.keys(patchData.value).length > 0 || deletedIcon.value || icon.value
|
||||
})
|
||||
return Object.keys(patchData.value).length > 0 || deletedIcon.value || icon.value;
|
||||
});
|
||||
|
||||
const markIconForDeletion = () => {
|
||||
deletedIcon.value = true
|
||||
icon.value = null
|
||||
previewImage.value = null
|
||||
}
|
||||
deletedIcon.value = true;
|
||||
icon.value = null;
|
||||
previewImage.value = null;
|
||||
};
|
||||
|
||||
const showPreviewImage = (files) => {
|
||||
const reader = new FileReader()
|
||||
const reader = new FileReader();
|
||||
|
||||
icon.value = files[0]
|
||||
deletedIcon.value = false
|
||||
icon.value = files[0];
|
||||
deletedIcon.value = false;
|
||||
|
||||
reader.readAsDataURL(icon.value)
|
||||
reader.readAsDataURL(icon.value);
|
||||
reader.onload = (event) => {
|
||||
previewImage.value = event.target.result
|
||||
}
|
||||
}
|
||||
previewImage.value = event.target.result;
|
||||
};
|
||||
};
|
||||
|
||||
const orgId = useRouteId()
|
||||
const orgId = useRouteId();
|
||||
|
||||
const onSaveChanges = useClientTry(async () => {
|
||||
if (hasChanges.value) {
|
||||
await patchOrganization(orgId, patchData.value)
|
||||
await patchOrganization(orgId, patchData.value);
|
||||
}
|
||||
|
||||
if (deletedIcon.value) {
|
||||
await deleteIcon()
|
||||
deletedIcon.value = false
|
||||
await deleteIcon();
|
||||
deletedIcon.value = false;
|
||||
} else if (icon.value) {
|
||||
await patchIcon(icon.value)
|
||||
icon.value = null
|
||||
await patchIcon(icon.value);
|
||||
icon.value = null;
|
||||
}
|
||||
|
||||
await refreshOrganization()
|
||||
await refreshOrganization();
|
||||
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Organization updated',
|
||||
text: 'Your organization has been updated.',
|
||||
type: 'success',
|
||||
})
|
||||
})
|
||||
group: "main",
|
||||
title: "Organization updated",
|
||||
text: "Your organization has been updated.",
|
||||
type: "success",
|
||||
});
|
||||
});
|
||||
|
||||
const onDeleteOrganization = useClientTry(async () => {
|
||||
await useBaseFetch(`organization/${orgId}`, {
|
||||
method: 'DELETE',
|
||||
method: "DELETE",
|
||||
apiVersion: 3,
|
||||
})
|
||||
});
|
||||
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Organization deleted',
|
||||
text: 'Your organization has been deleted.',
|
||||
type: 'success',
|
||||
})
|
||||
group: "main",
|
||||
title: "Organization deleted",
|
||||
text: "Your organization has been deleted.",
|
||||
type: "success",
|
||||
});
|
||||
|
||||
await navigateTo('/dashboard/organizations')
|
||||
})
|
||||
await navigateTo("/dashboard/organizations");
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.MANAGE_INVITES
|
||||
organizationPermissions.MANAGE_INVITES,
|
||||
)
|
||||
"
|
||||
@keypress.enter="() => onInviteTeamMember(organization.team, currentUsername)"
|
||||
@@ -33,7 +33,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.MANAGE_INVITES
|
||||
organizationPermissions.MANAGE_INVITES,
|
||||
)
|
||||
"
|
||||
@click="() => onInviteTeamMember(organization.team_id, currentUsername)"
|
||||
@@ -108,7 +108,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.EDIT_MEMBER
|
||||
organizationPermissions.EDIT_MEMBER,
|
||||
)
|
||||
"
|
||||
/>
|
||||
@@ -128,7 +128,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.EDIT_MEMBER
|
||||
organizationPermissions.EDIT_MEMBER,
|
||||
)
|
||||
"
|
||||
/>
|
||||
@@ -145,7 +145,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.EDIT_MEMBER_DEFAULT_PERMISSIONS
|
||||
organizationPermissions.EDIT_MEMBER_DEFAULT_PERMISSIONS,
|
||||
) || !isPermission(currentMember.permissions, permission)
|
||||
"
|
||||
:label="permToLabel(label)"
|
||||
@@ -165,7 +165,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.EDIT_MEMBER
|
||||
organizationPermissions.EDIT_MEMBER,
|
||||
) || !isPermission(currentMember.organization_permissions, permission)
|
||||
"
|
||||
:label="permToLabel(label)"
|
||||
@@ -179,7 +179,7 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.EDIT_MEMBER
|
||||
organizationPermissions.EDIT_MEMBER,
|
||||
)
|
||||
"
|
||||
@click="onUpdateTeamMember(organization.team_id, member)"
|
||||
@@ -193,11 +193,11 @@
|
||||
:disabled="
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.EDIT_MEMBER
|
||||
organizationPermissions.EDIT_MEMBER,
|
||||
) &&
|
||||
!isPermission(
|
||||
currentMember.organization_permissions,
|
||||
organizationPermissions.REMOVE_MEMBER
|
||||
organizationPermissions.REMOVE_MEMBER,
|
||||
)
|
||||
"
|
||||
@click="onRemoveMember(organization.team_id, member)"
|
||||
@@ -225,29 +225,29 @@ import {
|
||||
UserPlusIcon,
|
||||
UserXIcon as UserRemoveIcon,
|
||||
DropdownIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { Button, Badge, Avatar, Checkbox } from '@modrinth/ui'
|
||||
import { ref } from 'vue'
|
||||
import CrownIcon from '~/assets/images/utils/crown.svg?component'
|
||||
} from "@modrinth/assets";
|
||||
import { Button, Badge, Avatar, Checkbox } from "@modrinth/ui";
|
||||
import { ref } from "vue";
|
||||
import CrownIcon from "~/assets/images/utils/crown.svg?component";
|
||||
|
||||
import { removeTeamMember } from '~/helpers/teams.js'
|
||||
import { isPermission } from '~/utils/permissions.ts'
|
||||
import { removeTeamMember } from "~/helpers/teams.js";
|
||||
import { isPermission } from "~/utils/permissions.ts";
|
||||
|
||||
const { organization, refresh: refreshOrganization, currentMember } = inject('organizationContext')
|
||||
const { organization, refresh: refreshOrganization, currentMember } = inject("organizationContext");
|
||||
|
||||
const auth = await useAuth()
|
||||
const auth = await useAuth();
|
||||
|
||||
const currentUsername = ref('')
|
||||
const openTeamMembers = ref([])
|
||||
const currentUsername = ref("");
|
||||
const openTeamMembers = ref([]);
|
||||
|
||||
const allTeamMembers = ref(organization.value.members)
|
||||
const allTeamMembers = ref(organization.value.members);
|
||||
|
||||
watch(
|
||||
() => organization.value,
|
||||
() => {
|
||||
allTeamMembers.value = organization.value.members
|
||||
}
|
||||
)
|
||||
allTeamMembers.value = organization.value.members;
|
||||
},
|
||||
);
|
||||
|
||||
const projectPermissions = {
|
||||
UPLOAD_VERSION: 1 << 0,
|
||||
@@ -260,7 +260,7 @@ const projectPermissions = {
|
||||
DELETE_PROJECT: 1 << 7,
|
||||
VIEW_ANALYTICS: 1 << 8,
|
||||
VIEW_PAYOUTS: 1 << 9,
|
||||
}
|
||||
};
|
||||
|
||||
const organizationPermissions = {
|
||||
EDIT_DETAILS: 1 << 0,
|
||||
@@ -271,49 +271,49 @@ const organizationPermissions = {
|
||||
REMOVE_PROJECT: 1 << 5,
|
||||
DELETE_ORGANIZATION: 1 << 6,
|
||||
EDIT_MEMBER_DEFAULT_PERMISSIONS: 1 << 7,
|
||||
}
|
||||
};
|
||||
|
||||
const permToLabel = (key) => {
|
||||
const o = key.split('_').join(' ')
|
||||
return o.charAt(0).toUpperCase() + o.slice(1).toLowerCase()
|
||||
}
|
||||
const o = key.split("_").join(" ");
|
||||
return o.charAt(0).toUpperCase() + o.slice(1).toLowerCase();
|
||||
};
|
||||
|
||||
const leaveProject = async (teamId, uid) => {
|
||||
await removeTeamMember(teamId, uid)
|
||||
await navigateTo(`/organization/${organization.value.id}`)
|
||||
}
|
||||
await removeTeamMember(teamId, uid);
|
||||
await navigateTo(`/organization/${organization.value.id}`);
|
||||
};
|
||||
|
||||
const onLeaveProject = useClientTry(leaveProject)
|
||||
const onLeaveProject = useClientTry(leaveProject);
|
||||
|
||||
const onInviteTeamMember = useClientTry(async (teamId, username) => {
|
||||
const user = await useBaseFetch(`user/${username}`)
|
||||
const user = await useBaseFetch(`user/${username}`);
|
||||
const data = {
|
||||
user_id: user.id.trim(),
|
||||
}
|
||||
};
|
||||
await useBaseFetch(`team/${teamId}/members`, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
body: data,
|
||||
})
|
||||
await refreshOrganization()
|
||||
currentUsername.value = ''
|
||||
});
|
||||
await refreshOrganization();
|
||||
currentUsername.value = "";
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Member invited',
|
||||
group: "main",
|
||||
title: "Member invited",
|
||||
text: `${user.username} has been invited to the organization.`,
|
||||
type: 'success',
|
||||
})
|
||||
})
|
||||
type: "success",
|
||||
});
|
||||
});
|
||||
|
||||
const onRemoveMember = useClientTry(async (teamId, member) => {
|
||||
await removeTeamMember(teamId, member.user.id)
|
||||
await refreshOrganization()
|
||||
await removeTeamMember(teamId, member.user.id);
|
||||
await refreshOrganization();
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Member removed',
|
||||
group: "main",
|
||||
title: "Member removed",
|
||||
text: `${member.user.username} has been removed from the organization.`,
|
||||
type: 'success',
|
||||
})
|
||||
})
|
||||
type: "success",
|
||||
});
|
||||
});
|
||||
|
||||
const onUpdateTeamMember = useClientTry(async (teamId, member) => {
|
||||
const data = !member.is_owner
|
||||
@@ -326,36 +326,36 @@ const onUpdateTeamMember = useClientTry(async (teamId, member) => {
|
||||
: {
|
||||
payouts_split: member.payouts_split,
|
||||
role: member.role,
|
||||
}
|
||||
};
|
||||
await useBaseFetch(`team/${teamId}/members/${member.user.id}`, {
|
||||
method: 'PATCH',
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
})
|
||||
await refreshOrganization()
|
||||
});
|
||||
await refreshOrganization();
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Member updated',
|
||||
group: "main",
|
||||
title: "Member updated",
|
||||
text: `${member.user.username} has been updated.`,
|
||||
type: 'success',
|
||||
})
|
||||
})
|
||||
type: "success",
|
||||
});
|
||||
});
|
||||
|
||||
const onTransferOwnership = useClientTry(async (teamId, uid) => {
|
||||
const data = {
|
||||
user_id: uid,
|
||||
}
|
||||
};
|
||||
await useBaseFetch(`team/${teamId}/owner`, {
|
||||
method: 'PATCH',
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
})
|
||||
await refreshOrganization()
|
||||
});
|
||||
await refreshOrganization();
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Ownership transferred',
|
||||
group: "main",
|
||||
title: "Ownership transferred",
|
||||
text: `The ownership of ${organization.value.name} has been successfully transferred.`,
|
||||
type: 'success',
|
||||
})
|
||||
})
|
||||
type: "success",
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -120,14 +120,14 @@
|
||||
<p>
|
||||
Changes will be applied to
|
||||
<strong>{{ selectedProjects.length }}</strong> project{{
|
||||
selectedProjects.length > 1 ? 's' : ''
|
||||
selectedProjects.length > 1 ? "s" : ""
|
||||
}}.
|
||||
</p>
|
||||
<ul>
|
||||
<li
|
||||
v-for="project in selectedProjects.slice(
|
||||
0,
|
||||
editLinks.showAffected ? selectedProjects.length : 3
|
||||
editLinks.showAffected ? selectedProjects.length : 3,
|
||||
)"
|
||||
:key="project.id"
|
||||
>
|
||||
@@ -208,8 +208,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="table">
|
||||
<div class="table-row table-head">
|
||||
<div class="table-cell check-cell">
|
||||
<div class="table-head table-row">
|
||||
<div class="check-cell table-cell">
|
||||
<Checkbox
|
||||
:model-value="selectedProjects === sortedProjects"
|
||||
@update:model-value="
|
||||
@@ -227,7 +227,7 @@
|
||||
<div class="table-cell" />
|
||||
</div>
|
||||
<div v-for="project in sortedProjects" :key="`project-${project.id}`" class="table-row">
|
||||
<div class="table-cell check-cell">
|
||||
<div class="check-cell table-cell">
|
||||
<Checkbox
|
||||
:disabled="(project.permissions & EDIT_DETAILS) === EDIT_DETAILS"
|
||||
:model-value="selectedProjects.includes(project)"
|
||||
@@ -273,7 +273,7 @@
|
||||
<BoxIcon />
|
||||
<span>{{
|
||||
$formatProjectType(
|
||||
$getProjectTypeForDisplay(project.project_types[0] ?? 'project', project.loaders)
|
||||
$getProjectTypeForDisplay(project.project_types[0] ?? "project", project.loaders),
|
||||
)
|
||||
}}</span>
|
||||
</div>
|
||||
@@ -298,7 +298,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Multiselect } from 'vue-multiselect'
|
||||
import { Multiselect } from "vue-multiselect";
|
||||
import {
|
||||
BoxIcon,
|
||||
SettingsIcon,
|
||||
@@ -310,215 +310,215 @@ import {
|
||||
SaveIcon,
|
||||
SortAscendingIcon,
|
||||
SortDescendingIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { Button, Modal, Avatar, CopyCode, Badge, Checkbox } from '@modrinth/ui'
|
||||
} from "@modrinth/assets";
|
||||
import { Button, Modal, Avatar, CopyCode, Badge, Checkbox } from "@modrinth/ui";
|
||||
|
||||
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
||||
import OrganizationProjectTransferModal from '~/components/ui/OrganizationProjectTransferModal.vue'
|
||||
import ModalCreation from "~/components/ui/ModalCreation.vue";
|
||||
import OrganizationProjectTransferModal from "~/components/ui/OrganizationProjectTransferModal.vue";
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const { formatMessage } = useVIntl();
|
||||
|
||||
const { organization, projects, refresh } = inject('organizationContext')
|
||||
const { organization, projects, refresh } = inject("organizationContext");
|
||||
|
||||
const auth = await useAuth()
|
||||
const auth = await useAuth();
|
||||
|
||||
const { data: userProjects, refresh: refreshUserProjects } = await useAsyncData(
|
||||
`user/${auth.value.user.id}/projects`,
|
||||
() => useBaseFetch(`user/${auth.value.user.id}/projects`),
|
||||
{
|
||||
watch: [auth],
|
||||
}
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
const usersOwnedProjects = ref([])
|
||||
const usersOwnedProjects = ref([]);
|
||||
|
||||
watch(
|
||||
() => userProjects.value,
|
||||
async () => {
|
||||
if (!userProjects.value) return
|
||||
if (!userProjects.value.length) return
|
||||
if (!userProjects.value) return;
|
||||
if (!userProjects.value.length) return;
|
||||
|
||||
const projects = userProjects.value.filter((project) => project.organization === null)
|
||||
const projects = userProjects.value.filter((project) => project.organization === null);
|
||||
|
||||
const teamIds = projects.map((project) => project?.team).filter((x) => x)
|
||||
const teamIds = projects.map((project) => project?.team).filter((x) => x);
|
||||
// Shape of teams is member[][]
|
||||
const teams = await useBaseFetch(`teams?ids=${JSON.stringify(teamIds)}`, {
|
||||
apiVersion: 3,
|
||||
})
|
||||
});
|
||||
// for each team id, figure out if the user is a member, and is_owner. Then filter the projects to only include those that are owned by the user
|
||||
const ownedTeamIds = teamIds.filter((_tid, i) => {
|
||||
const team = teams?.[i]
|
||||
if (!team) return false
|
||||
const member = team.find((member) => member.user.id === auth.value.user.id)
|
||||
return member && member.is_owner
|
||||
})
|
||||
const ownedProjects = projects.filter((project) => ownedTeamIds.includes(project.team))
|
||||
usersOwnedProjects.value = ownedProjects
|
||||
const team = teams?.[i];
|
||||
if (!team) return false;
|
||||
const member = team.find((member) => member.user.id === auth.value.user.id);
|
||||
return member && member.is_owner;
|
||||
});
|
||||
const ownedProjects = projects.filter((project) => ownedTeamIds.includes(project.team));
|
||||
usersOwnedProjects.value = ownedProjects;
|
||||
}, // watch options
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
const onProjectTransferSubmit = async (projects) => {
|
||||
try {
|
||||
for (const project of projects) {
|
||||
await useBaseFetch(`organization/${organization.value.id}/projects`, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
project_id: project.id,
|
||||
}),
|
||||
apiVersion: 3,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
await refresh()
|
||||
await refreshUserProjects()
|
||||
await refresh();
|
||||
await refreshUserProjects();
|
||||
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Success',
|
||||
text: 'Transferred selected projects to organization.',
|
||||
type: 'success',
|
||||
})
|
||||
group: "main",
|
||||
title: "Success",
|
||||
text: "Transferred selected projects to organization.",
|
||||
type: "success",
|
||||
});
|
||||
} catch (err) {
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
text: err?.data?.description || err?.message || err || 'Unknown error',
|
||||
type: 'error',
|
||||
})
|
||||
console.error(err)
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: err?.data?.description || err?.message || err || "Unknown error",
|
||||
type: "error",
|
||||
});
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const EDIT_DETAILS = 1 << 2
|
||||
const EDIT_DETAILS = 1 << 2;
|
||||
|
||||
const updateSort = (inputProjects, sort, descending) => {
|
||||
let sortedArray = inputProjects
|
||||
let sortedArray = inputProjects;
|
||||
switch (sort) {
|
||||
case 'Name':
|
||||
case "Name":
|
||||
sortedArray = inputProjects.slice().sort((a, b) => {
|
||||
return a.name.localeCompare(b.name)
|
||||
})
|
||||
break
|
||||
case 'Status':
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
break;
|
||||
case "Status":
|
||||
sortedArray = inputProjects.slice().sort((a, b) => {
|
||||
if (a.status < b.status) {
|
||||
return -1
|
||||
return -1;
|
||||
}
|
||||
if (a.status > b.status) {
|
||||
return 1
|
||||
return 1;
|
||||
}
|
||||
return 0
|
||||
})
|
||||
break
|
||||
case 'Type':
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
case "Type":
|
||||
sortedArray = inputProjects.slice().sort((a, b) => {
|
||||
if (a.project_type < b.project_type) {
|
||||
return -1
|
||||
return -1;
|
||||
}
|
||||
if (a.project_type > b.project_type) {
|
||||
return 1
|
||||
return 1;
|
||||
}
|
||||
return 0
|
||||
})
|
||||
break
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break
|
||||
break;
|
||||
}
|
||||
|
||||
if (descending) {
|
||||
sortedArray = sortedArray.reverse()
|
||||
sortedArray = sortedArray.reverse();
|
||||
}
|
||||
|
||||
return sortedArray
|
||||
}
|
||||
return sortedArray;
|
||||
};
|
||||
|
||||
const sortedProjects = ref(updateSort(projects.value, 'Name'))
|
||||
const selectedProjects = ref([])
|
||||
const sortBy = ref('Name')
|
||||
const descending = ref(false)
|
||||
const editLinksModal = ref(null)
|
||||
const sortedProjects = ref(updateSort(projects.value, "Name"));
|
||||
const selectedProjects = ref([]);
|
||||
const sortBy = ref("Name");
|
||||
const descending = ref(false);
|
||||
const editLinksModal = ref(null);
|
||||
|
||||
watch(
|
||||
() => projects.value,
|
||||
(newVal) => {
|
||||
sortedProjects.value = updateSort(newVal, sortBy.value, descending.value)
|
||||
}
|
||||
)
|
||||
sortedProjects.value = updateSort(newVal, sortBy.value, descending.value);
|
||||
},
|
||||
);
|
||||
|
||||
const emptyLinksData = {
|
||||
showAffected: false,
|
||||
source: {
|
||||
val: '',
|
||||
val: "",
|
||||
clear: false,
|
||||
},
|
||||
discord: {
|
||||
val: '',
|
||||
val: "",
|
||||
clear: false,
|
||||
},
|
||||
wiki: {
|
||||
val: '',
|
||||
val: "",
|
||||
clear: false,
|
||||
},
|
||||
issues: {
|
||||
val: '',
|
||||
val: "",
|
||||
clear: false,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const editLinks = ref(emptyLinksData)
|
||||
const editLinks = ref(emptyLinksData);
|
||||
|
||||
const updateDescending = () => {
|
||||
descending.value = !descending.value
|
||||
sortedProjects.value = updateSort(sortedProjects.value, sortBy.value, descending.value)
|
||||
}
|
||||
descending.value = !descending.value;
|
||||
sortedProjects.value = updateSort(sortedProjects.value, sortBy.value, descending.value);
|
||||
};
|
||||
|
||||
const onBulkEditLinks = useClientTry(async () => {
|
||||
const linkData = editLinks.value
|
||||
const linkData = editLinks.value;
|
||||
|
||||
const baseData = {}
|
||||
const baseData = {};
|
||||
|
||||
if (linkData.issues.clear) {
|
||||
baseData.issues_url = null
|
||||
baseData.issues_url = null;
|
||||
} else if (linkData.issues.val.trim().length > 0) {
|
||||
baseData.issues_url = linkData.issues.val.trim()
|
||||
baseData.issues_url = linkData.issues.val.trim();
|
||||
}
|
||||
|
||||
if (linkData.source.clear) {
|
||||
baseData.source_url = null
|
||||
baseData.source_url = null;
|
||||
} else if (linkData.source.val.trim().length > 0) {
|
||||
baseData.source_url = linkData.source.val.trim()
|
||||
baseData.source_url = linkData.source.val.trim();
|
||||
}
|
||||
|
||||
if (linkData.wiki.clear) {
|
||||
baseData.wiki_url = null
|
||||
baseData.wiki_url = null;
|
||||
} else if (linkData.wiki.val.trim().length > 0) {
|
||||
baseData.wiki_url = linkData.wiki.val.trim()
|
||||
baseData.wiki_url = linkData.wiki.val.trim();
|
||||
}
|
||||
|
||||
if (linkData.discord.clear) {
|
||||
baseData.discord_url = null
|
||||
baseData.discord_url = null;
|
||||
} else if (linkData.discord.val.trim().length > 0) {
|
||||
baseData.discord_url = linkData.discord.val.trim()
|
||||
baseData.discord_url = linkData.discord.val.trim();
|
||||
}
|
||||
|
||||
await useBaseFetch(`projects?ids=${JSON.stringify(selectedProjects.value.map((x) => x.id))}`, {
|
||||
method: 'PATCH',
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(baseData),
|
||||
})
|
||||
});
|
||||
|
||||
editLinksModal.value.hide()
|
||||
editLinksModal.value.hide();
|
||||
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'Success',
|
||||
group: "main",
|
||||
title: "Success",
|
||||
text: "Bulk edited selected project's links.",
|
||||
type: 'success',
|
||||
})
|
||||
type: "success",
|
||||
});
|
||||
|
||||
selectedProjects.value = []
|
||||
editLinks.value = emptyLinksData
|
||||
})
|
||||
selectedProjects.value = [];
|
||||
editLinks.value = emptyLinksData;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table {
|
||||
@@ -551,7 +551,7 @@ const onBulkEditLinks = useClientTry(async () => {
|
||||
|
||||
.table-row {
|
||||
display: grid;
|
||||
grid-template: 'checkbox icon name type settings' 'checkbox icon id status settings';
|
||||
grid-template: "checkbox icon name type settings" "checkbox icon id status settings";
|
||||
grid-template-columns:
|
||||
min-content min-content minmax(min-content, 2fr)
|
||||
minmax(min-content, 1fr) min-content;
|
||||
@@ -588,7 +588,7 @@ const onBulkEditLinks = useClientTry(async () => {
|
||||
}
|
||||
|
||||
.table-head {
|
||||
grid-template: 'checkbox settings';
|
||||
grid-template: "checkbox settings";
|
||||
grid-template-columns: min-content minmax(min-content, 1fr);
|
||||
|
||||
:nth-child(2),
|
||||
@@ -604,7 +604,7 @@ const onBulkEditLinks = useClientTry(async () => {
|
||||
@media screen and (max-width: 560px) {
|
||||
.table-row {
|
||||
display: grid;
|
||||
grid-template: 'checkbox icon name settings' 'checkbox icon id settings' 'checkbox icon type settings' 'checkbox icon status settings';
|
||||
grid-template: "checkbox icon name settings" "checkbox icon id settings" "checkbox icon type settings" "checkbox icon status settings";
|
||||
grid-template-columns: min-content min-content minmax(min-content, 1fr) min-content;
|
||||
|
||||
:nth-child(5) {
|
||||
@@ -613,7 +613,7 @@ const onBulkEditLinks = useClientTry(async () => {
|
||||
}
|
||||
|
||||
.table-head {
|
||||
grid-template: 'checkbox settings';
|
||||
grid-template: "checkbox settings";
|
||||
grid-template-columns: min-content minmax(min-content, 1fr);
|
||||
}
|
||||
}
|
||||
@@ -652,7 +652,7 @@ const onBulkEditLinks = useClientTry(async () => {
|
||||
width: -moz-fit-content;
|
||||
}
|
||||
|
||||
.label-button[data-active='true'] {
|
||||
.label-button[data-active="true"] {
|
||||
--background-color: var(--color-red);
|
||||
--text-color: var(--color-brand-inverted);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user