mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-18 23:04:20 +01:00
feat: built api & db tables for skills/roles and updating/querying them
This commit is contained in:
@@ -27,14 +27,29 @@ const BaseUser = interfaceType({
|
|||||||
t.string('location')
|
t.string('location')
|
||||||
t.nonNull.list.nonNull.field('roles', {
|
t.nonNull.list.nonNull.field('roles', {
|
||||||
type: MakerRole,
|
type: MakerRole,
|
||||||
resolve: (parent) => {
|
resolve: async (parent) => {
|
||||||
return []
|
const data = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: parent.id
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
roles: {
|
||||||
|
select: {
|
||||||
|
role: true,
|
||||||
|
level: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return data.roles.map(data => {
|
||||||
|
return ({ ...data.role, level: data.level })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.nonNull.list.nonNull.field('skills', {
|
t.nonNull.list.nonNull.field('skills', {
|
||||||
type: MakerSkill,
|
type: MakerSkill,
|
||||||
resolve: (parent) => {
|
resolve: (parent) => {
|
||||||
return []
|
return prisma.user.findUnique({ where: { id: parent.id } }).skills();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.nonNull.list.nonNull.field('tournaments', {
|
t.nonNull.list.nonNull.field('tournaments', {
|
||||||
@@ -112,7 +127,7 @@ const getAllMakersRoles = extendType({
|
|||||||
t.nonNull.list.nonNull.field('getAllMakersRoles', {
|
t.nonNull.list.nonNull.field('getAllMakersRoles', {
|
||||||
type: GenericMakerRole,
|
type: GenericMakerRole,
|
||||||
async resolve(parent, args, context) {
|
async resolve(parent, args, context) {
|
||||||
return []
|
return prisma.workRole.findMany();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -133,7 +148,7 @@ const getAllMakersSkills = extendType({
|
|||||||
t.nonNull.list.nonNull.field('getAllMakersSkills', {
|
t.nonNull.list.nonNull.field('getAllMakersSkills', {
|
||||||
type: MakerSkill,
|
type: MakerSkill,
|
||||||
async resolve(parent, args, context) {
|
async resolve(parent, args, context) {
|
||||||
return []
|
return prisma.skill.findMany();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -389,16 +404,38 @@ const updateProfileRoles = extendType({
|
|||||||
// Do some validation
|
// Do some validation
|
||||||
if (!user)
|
if (!user)
|
||||||
throw new Error("You have to login");
|
throw new Error("You have to login");
|
||||||
// TODO: validate new data
|
|
||||||
|
|
||||||
|
await prisma.user.update({
|
||||||
|
where: {
|
||||||
|
id: user.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
skills: {
|
||||||
|
set: [],
|
||||||
|
},
|
||||||
|
roles: {
|
||||||
|
deleteMany: {}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Preprocess & insert
|
|
||||||
|
|
||||||
return prisma.user.update({
|
return prisma.user.update({
|
||||||
where: {
|
where: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
},
|
},
|
||||||
// data: removeNulls(args.data)
|
data: {
|
||||||
|
skills: {
|
||||||
|
connect: args.data.skills,
|
||||||
|
},
|
||||||
|
roles: {
|
||||||
|
create: args.data.roles.map(r => {
|
||||||
|
console.log(({ roleId: r.id, level: r.level }));
|
||||||
|
return ({ roleId: r.id, level: r.level })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "UserKey" ALTER COLUMN "name" SET DEFAULT E'My new wallet key';
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "UsersOnWorkRoles" (
|
||||||
|
"userId" INTEGER NOT NULL,
|
||||||
|
"roleId" INTEGER NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "UsersOnWorkRoles_pkey" PRIMARY KEY ("userId","roleId")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "WorkRole" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"title" TEXT NOT NULL,
|
||||||
|
"icon" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "WorkRole_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Skill" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"title" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Skill_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "_SkillToUser" (
|
||||||
|
"A" INTEGER NOT NULL,
|
||||||
|
"B" INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "WorkRole_title_key" ON "WorkRole"("title");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Skill_title_key" ON "Skill"("title");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "_SkillToUser_AB_unique" ON "_SkillToUser"("A", "B");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "_SkillToUser_B_index" ON "_SkillToUser"("B");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "UsersOnWorkRoles" ADD CONSTRAINT "UsersOnWorkRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "UsersOnWorkRoles" ADD CONSTRAINT "UsersOnWorkRoles_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "WorkRole"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "_SkillToUser" ADD FOREIGN KEY ("A") REFERENCES "Skill"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "_SkillToUser" ADD FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Added the required column `level` to the `UsersOnWorkRoles` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "UsersOnWorkRoles" ADD COLUMN "level" TEXT NOT NULL;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Changed the type of `level` on the `UsersOnWorkRoles` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "UsersOnWorkRoles" DROP COLUMN "level",
|
||||||
|
ADD COLUMN "level" INTEGER NOT NULL;
|
||||||
@@ -65,6 +65,8 @@ model User {
|
|||||||
posts_comments PostComment[]
|
posts_comments PostComment[]
|
||||||
donations Donation[]
|
donations Donation[]
|
||||||
userKeys UserKey[]
|
userKeys UserKey[]
|
||||||
|
skills Skill[]
|
||||||
|
roles UsersOnWorkRoles[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model UserKey {
|
model UserKey {
|
||||||
@@ -75,6 +77,31 @@ model UserKey {
|
|||||||
user_id Int?
|
user_id Int?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model UsersOnWorkRoles {
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
|
userId Int
|
||||||
|
role WorkRole @relation(fields: [roleId], references: [id])
|
||||||
|
roleId Int
|
||||||
|
|
||||||
|
level Int
|
||||||
|
|
||||||
|
@@id([userId, roleId])
|
||||||
|
}
|
||||||
|
|
||||||
|
model WorkRole {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
title String @unique
|
||||||
|
icon String
|
||||||
|
users UsersOnWorkRoles[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model Skill {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
title String @unique
|
||||||
|
|
||||||
|
users User[]
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------
|
// -----------------
|
||||||
// Projects
|
// Projects
|
||||||
// -----------------
|
// -----------------
|
||||||
|
|||||||
@@ -418,10 +418,103 @@ const hackathons = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const roles = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Frontend Dev",
|
||||||
|
icon: "💄"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Backend Dev",
|
||||||
|
icon: "💻️"
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
title: "UI/UX Designer",
|
||||||
|
icon: "🌈️️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "Community Manager",
|
||||||
|
icon: "🎉️️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: "Founder",
|
||||||
|
icon: "🦄️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: "Marketer",
|
||||||
|
icon: "🚨️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
title: "Content Creator",
|
||||||
|
icon: "🎥️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
title: "Researcher",
|
||||||
|
icon: "🔬"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
title: "Data engineer",
|
||||||
|
icon: "💿️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
title: "Growth hacker",
|
||||||
|
icon: "📉️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
title: "Technical Writer",
|
||||||
|
icon: "✍️️"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const skills = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Figma"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Prototyping"
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
title: "Writing"
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
title: "CSS"
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
title: "React.js"
|
||||||
|
}, {
|
||||||
|
id: 6,
|
||||||
|
title: "Wordpress"
|
||||||
|
}, {
|
||||||
|
id: 7,
|
||||||
|
title: "Principle app"
|
||||||
|
}, {
|
||||||
|
id: 8,
|
||||||
|
title: "UX design"
|
||||||
|
}, {
|
||||||
|
id: 9,
|
||||||
|
title: "User research"
|
||||||
|
}, {
|
||||||
|
id: 10,
|
||||||
|
title: "User testing"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
categories,
|
categories,
|
||||||
projects,
|
projects,
|
||||||
tags,
|
tags,
|
||||||
hackathons,
|
hackathons,
|
||||||
|
roles,
|
||||||
|
skills,
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
const { PrismaClient } = require("@prisma/client");
|
const { PrismaClient } = require("@prisma/client");
|
||||||
const { generatePrivateKey, getPublicKey } = require("../../api/utils/nostr-tools");
|
const { generatePrivateKey, getPublicKey } = require("../../api/utils/nostr-tools");
|
||||||
const { categories, projects, tags, hackathons } = require("./data");
|
const { categories, projects, tags, hackathons, roles, skills } = require("./data");
|
||||||
const Chance = require('chance');
|
const Chance = require('chance');
|
||||||
const { getCoverImage, randomItems, random } = require("./helpers");
|
const { getCoverImage, randomItems, random } = require("./helpers");
|
||||||
|
|
||||||
@@ -58,7 +58,11 @@ async function main() {
|
|||||||
|
|
||||||
// await createHackathons();
|
// await createHackathons();
|
||||||
|
|
||||||
await fillUserKeysTable()
|
// await fillUserKeysTable()
|
||||||
|
|
||||||
|
// await createRoles();
|
||||||
|
|
||||||
|
// await createSkills();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +173,26 @@ async function fillUserKeysTable() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createRoles() {
|
||||||
|
console.log("Creating Users Roles");
|
||||||
|
await prisma.workRole.createMany({
|
||||||
|
data: roles.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
icon: item.icon,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createSkills() {
|
||||||
|
console.log("Creating Users Skills");
|
||||||
|
await prisma.skill.createMany({
|
||||||
|
data: skills.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const schema: yup.SchemaOf<IRolesSkillsForm> = yup.object({
|
|||||||
roles: yup.array().of(
|
roles: yup.array().of(
|
||||||
yup.object().shape({
|
yup.object().shape({
|
||||||
id: yup.number().required(),
|
id: yup.number().required(),
|
||||||
role: yup.string().required(),
|
level: yup.string().required(),
|
||||||
}).required()
|
}).required()
|
||||||
).required(),
|
).required(),
|
||||||
skills: yup.array().of(
|
skills: yup.array().of(
|
||||||
@@ -70,7 +70,10 @@ export default function PreferencesTab() {
|
|||||||
const toastId = toast.loading("Saving changes...", NotificationsService.defaultOptions)
|
const toastId = toast.loading("Saving changes...", NotificationsService.defaultOptions)
|
||||||
mutate({
|
mutate({
|
||||||
variables: {
|
variables: {
|
||||||
data
|
data: {
|
||||||
|
roles: data.roles.map(v => ({ id: v.id, level: v.level })),
|
||||||
|
skills: data.skills.map(v => ({ id: v.id })),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onCompleted: ({ updateProfileRoles }) => {
|
onCompleted: ({ updateProfileRoles }) => {
|
||||||
if (updateProfileRoles) {
|
if (updateProfileRoles) {
|
||||||
@@ -113,7 +116,7 @@ export default function PreferencesTab() {
|
|||||||
<SaveChangesCard
|
<SaveChangesCard
|
||||||
isLoading={mutationStatus.loading}
|
isLoading={mutationStatus.loading}
|
||||||
isDirty={isDirty}
|
isDirty={isDirty}
|
||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit, e => console.log(e))}
|
||||||
onCancel={() => reset()}
|
onCancel={() => reset()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default function UpdateRolesCard(props: Props) {
|
|||||||
{props.value.map(role => {
|
{props.value.map(role => {
|
||||||
const { title, icon } = props.allRoles.find(r => r.id === role.id)!;
|
const { title, icon } = props.allRoles.find(r => r.id === role.id)!;
|
||||||
|
|
||||||
return <>
|
return <React.Fragment key={role.id}>
|
||||||
<p className="shrink-0 text-body4 whitespace-nowrap">{icon} {title}</p>
|
<p className="shrink-0 text-body4 whitespace-nowrap">{icon} {title}</p>
|
||||||
<div className="flex flex-wrap gap-8 grow text-body5 mb-8 last-of-type:mb-0">
|
<div className="flex flex-wrap gap-8 grow text-body5 mb-8 last-of-type:mb-0">
|
||||||
{[RoleLevelEnum.Beginner, RoleLevelEnum.Hobbyist, RoleLevelEnum.Intermediate, RoleLevelEnum.Advanced, RoleLevelEnum.Pro].map(r =>
|
{[RoleLevelEnum.Beginner, RoleLevelEnum.Hobbyist, RoleLevelEnum.Intermediate, RoleLevelEnum.Advanced, RoleLevelEnum.Pro].map(r =>
|
||||||
@@ -71,7 +71,7 @@ export default function UpdateRolesCard(props: Props) {
|
|||||||
onClick={() => setLevel(role.id, r)}
|
onClick={() => setLevel(role.id, r)}
|
||||||
>{r}</button>
|
>{r}</button>
|
||||||
)}</div>
|
)}</div>
|
||||||
</>
|
</React.Fragment >
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>}
|
</div>}
|
||||||
|
|||||||
Reference in New Issue
Block a user