在VUE中使用Cloudinary和XATA构建简历生成器
#javascript #vue #xata #cloudinary

通常称为简历的课程,总结了某人的职业,资格和教育。精心制作的简历突出了一个人的成就或熟练度是一门艺术。
对于初级或入门级专业人员寻找他们的第一份工作,有时需要获得下一个角色才能获得一个出色的简历,可以充分说明自己的能力而不会感到无聊。

本文将讨论使用Cloudinary和Xata在VUE中构建简历。

Cloudinary是一个基于云的视频和图像管理平台,可提供用于管理和转换网络上使用的上传资产的服务。用于文本检测和提取的OCR附加组件也是Cloudinary渲染的解决方案的一部分。

XATA是一个Serverless Data platform,它通过提供SaaS电子表格应用程序的可用性来简化开发人员如何与数据合作。

github

查看完整的源代码here

Netlify

可以找到与实时演示的链接。

先决条件

了解本文需要以下内容:

  • node.js的安装
  • JavaScript的基本知识
  • 一个云帐户(注册here
  • 使用Xata创建一个免费帐户

创建VUE应用程序

我们将使用vue create <project-name>命令创建一个新的VUE应用。
脚手架的过程将提供一个选项列表,看起来像这样:

Vue application scaffolding options

我们可以通过运行以下命令来启动VUE应用程序:

cd <project name>
npm run serve

vue将依次启动一个热加载的开发环境,默认情况下可以在http://localhost:8080访问。

创建XATA数据库

要在XATA上创建一个数据库,我们需要登录我们的Accoount或创建新的account。接下来,我们将转到用户仪表板上的数据库选项卡以创建适当的数据库。

Database creation on Xata

然后,我们将创建一个新表格,并添加我们希望该表拥有的适当记录/字段。在这种情况下,我们使用emailpasswordusername Records创建了一个user表。
这些记录表示我们将在应用程序中跟踪并保存到数据库的数据。

Table creation on Xata

在我们的VUE应用程序中设置XATA

安装XATA

要在我们的项目中使用XATA,我们将从命令行中安装XATA软件开发套件(SDK)。

npx xata

之后,我们可以通过运行以下命令来初始化XATA以供在我们的应用程序中使用:

xata init

XATA将向我们提供我们可以选择的各种选项。最后,XATA将生成一些用于使用的文件,其中我们将拥有.xatrc.env文件。
我们需要在我们的VUE应用程序中将XATA API密钥的名称编辑为以下一个,以允许VUE应用程序拾取环境变量。

VUE_APP_XATA_API_KEY="add your api key"

云设置

对于我们的应用程序资产管理,如果您已经需要单击here创建一个用Cloudinary创建一个帐户。创建帐户是完全免费的。
在将其配置为VUE应用程序之前,我们将需要使用以下命令安装Cloudinary Vue.js SDK

npm install cloudinary-vue

我们需要通过导航到main.js并将以下内容添加到文件中。

import Cloudinary from "cloudinary-vue";

Vue.use(Cloudinary, {
  configuration: { 
    cloudName: "XXX" //add the cloudinary cloudname here,
    secure: true }
});

我们将上传我们要使用的模板到我们的Cloudinary应用程序。在这种情况下,我们使用了帮助Danny Thompson担任他的第一个技术角色的CV template

创建注册页面

我们将需要一个用户注册我们的应用程序以生成简历。为此,我们将创建一个名为views/SignupView.vue的文件,并在其中添加以下代码:


<template>
  <div class="bg-gold vh-100">
    <div class="pv5 ph2">
      <form class="ba b--black bw4 bg-white br2 mw6 w-40-m w-70 w-20-l center pa3 shadow-5" @submit.prevent="signUp">
        <h2 class="ttc tc">
          Sign up
        </h2>
        <label for="name" class="db mb2 black-70">Name</label>
        <input
          id="name"
          v-model="username"
          name="name"
          type="text"
          class="db mb3 w-100 br2 ph2 pv3 ba bw1 b--black"
          placeholder="John Doe"
        >
        <label for="email" class="db mb2 black-70">Email</label>
        <input
          id="email"
          v-model="email"
          name="email"
          type="email"
          class="db mb3 w-100 br2 ph2 pv3 ba bw1 b--black"
          placeholder="example@email.com"
        >
        <label for="password" class="db mb2 black-70">Password</label>
        <input
          id="password"
          v-model="password"
          name="password"
          type="password"
          class="db mb3 w-100 br2 ph2 pv3 ba bw1 b--black"
          placeholder="••••••••"
        >
        <button type="submit" class="center db pa3 mb3 tracked bg-black ba br3 white pointer hover-black hover-bg-gold bg-animate pointer">
          Sign up
        </button>
        <p>Already have an account? <a href="/signin" class="black-70 b">Sign in</a> </p>
      </form>
    </div>
  </div>
</template>

这样,我们已成功为我们的注册页面创建了一个接口。现在,我们将添加身份验证和授权的功能。

我们将使用XATA实现我们的身份验证目标。为此,我们将其添加到SingupView.view文件:

<script>
import { getXataClient } from '@/xata'
export default {
  name: 'signup',
  data: () => ({
    username: '',
    email: '',
    password: '',
  }),
  methods: {
    async signUp() {
      const xata = getXataClient()
      const user = await xata.db.users.filter('username', this.username).getFirst()
      if (!user) {
        await xata.db.users.create({
          username: this.username,
          password: this.password,
          email: this.email
        }).then((res) => {
          this.$router.push({path:`/dashboard/${res.username}`, params: user})
        })
        this.$notify({type: 'success', text: "Account creation successful!" })
      }
    }
  }
}
</script>

从上面的代码块中,我们实现了以下内容:

  • 导入XATA客户端
  • 检查用户是否存在并创建新用户,如果当前用户不存在
  • 在成功的帐户创建中,用户的视图已更改为仪表板,从那里他们可以生成CV。

此时,我们的应用程序应该看起来像以下内容:

Signup interface

创建标志页

我们还需要创建选项,以允许已经创建帐户的人签名。为此,我们将创建一个名为SigninView.vue的文件,并添加以下代码:


<template>
  <div class="bg-gold vh-100">
    <div class=" pv5 ph2">
      <form class="ba b--black bw4 bg-white br2 mw6 w-40-m w-70 w-20-l center pa3 shadow-5" @submit.prevent="signIn">
        <h2 class="ttc tc">
          Sign In
        </h2>
        <label for="email" class="db mb2 black-70">Email</label>
        <input
          id="email"
          v-model="email"
          name="email"
          type="email"
          class="db mb3 w-100 br2 ph2 pv3 ba bw1 b--black"
          placeholder="example@email.com"
        >
        <label for="password" class="db mb2 black-70">Password</label>
        <input
          id="password"
          v-model="password"
          name="password"
          type="password"
          class="db mb3 w-100 br2 ph2 pv3 ba bw1 b--black"
          placeholder="••••••••"
        >
        <button type="submit" class="center db pa3 mb3 tracked bg-black ba br3 white pointer hover-black hover-bg-gold bg-animate pointer">
          Sign in
        </button>
      </form>
    </div>
  </div>
</template>

以上为我们创建了一个符号接口。但是,我们需要围绕它包裹一些功能,以使其按预期工作。
为此,我们将在SigninView.vue中添加下面的代码。


<script>
import { getXataClient } from '@/xata'
export default {
  data: () => ({
    email: '',
    password: ''
  }),
  methods: {
    async signIn() {
      const xata = getXataClient()
      const user = await xata.db.users.filter('email', this.email).getFirst()
      if (!this.email || !this.password ){
        this.$notify({type: 'error', text: "Please fill all empty fields"})
      } else if (this.email !== user.email || this.password !== user.password){
        this.$notify({type: 'error', text: "Incorrect credentials"})
        this.email = '';
        this.password = '';
      } else {
        this.$notify({type: 'success', text: "Login successful!"})
        this.$router.push({path:`/dashboard/${user.username}`, params: user})
      }
    }
  }

}
</script>

从上面,我们创建了一个称为signIn函数的函数,可执行以下操作:

  • 导入XATA客户端
  • 检查用户是否通过emailpassword,然后返回适当的错误,如果不可用
  • 交叉检查输入的电子邮件和密码以确保与数据库中的电子邮件和密码匹配
  • 如果支票通过,则将页面路由到仪表板,用户可以在其中生成CV

此时,我们的界面看起来像这样:

Signin interface

创建仪表板

我们的仪表板是大部分作品发生的地方,因为这是我们生成简历的地方。我们将首先创建一个名为TheDashboardBody.vue的文件,然后我们添加一个表单,允许用户添加想要在其cv上显示的输入。


<template>
  <div class="flex absolute vh-auto top-4 left-2 right-2 w-90 center mw9">
  <div class="mr3 bg-white w-70 br3 pa3">
    <form @submit.prevent="createResume" class="flex justify-between flex-wrap">
      <div class="w-50-l w-100">
        <label for="email" class="db mb3 black-70 ttu fw7">Firstname</label>
        <input
          id="firstname"
          v-model="userData.firstname"
          name="firstname"
          type="text"
          class="db mb3 w-90 br2 pa2 ba bw1 b--black bg-black-05"
          placeholder="Firstname"
        >
      </div>
      <div class="w-50-l w-100">
        <label for="lastname" class="db mb3 black-70 ttu fw7">Lastname</label>
        <input
          id="lastname"
          v-model="userData.lastname"
          name="lastname"
          type="text"
          class="db mb3 w-90 br2 pa2 ba bw1 b--black bg-black-05"
          placeholder="Lastname"
        >
          </div>
          <div class="dn" v-if="showTemplate">
          <TheResumeTemplate :userData="userData" ref="ref" />
        </div>

        <div class="w-100">
          <button type="submit" class="f6 ttu tracked black-80 bg-black pa3 br3 white bb link b--black hover-black hover-bg-gold bg-animate pointer">Create Resume</button>
        </div>
        </form>
      </div>
      <div class="bg-white w-30 br3 pa3">
      <iframe :src="iframeSRC ? iframeSRC : initialSRC" width="100%" height="100%" />
    </div>
  </div>
</template>

上面是仪表板接口的外观模板。
我们添加了将从上面添加到CV的数据的输入字段。我们还添加了一个以PDF形式显示生成的CV的iframe。

现在,我们将添加功能以实现我们希望在生成的PDF中看到的更改。


<script>
import TheResumeTemplate from "@/components/TheResumeTemplate.vue";
export default {
  components: {
    TheResumeTemplate,
  },
  data: () => ({
    userData: {
      firstname: '',
      lastname: '',
      },
    showTemplate: false,
    iframeSRC: '',
    initialSRC: 'https://res.cloudinary.com/xxx/image/upload/v1667335911/cv_gen.pdf'
  }),
  methods: {
    createResume(){
      if(!this.userData.firstname){
        this.showTemplate = false
      } else {
        this.showTemplate = true
        this.$nextTick(() => {
          this.iframeSRC = this.$refs.ref.$refs.ref.$el.src;
        });
      }
    }
  }

}
</script>

从上面,我们可以将我们的createResume方法连接到模板,从而使我们能够生成PDF。
该界面的完整代码和此仪表板的功能可以在此github gist中找到。

添加云的简历模板

我们将采用Cloudinary的强大功能来生成和覆盖内容,以完成我们的简历生成。为此,我们将创建一个名为TheResumeTemplate.vue的新文件并添加下面的代码。


<template>
  <div>
    <cld-image publicId="cv_gen.pdf" ref="ref" >
    <cld-transformation flags="rasterize" />
      <cld-transformation :overlay="{fontFamily: 'Open Sans', fontSize: 75, text: `${userData.firstname} ${userData.lastname}`}" color="#58697B" gravity="west" x="100" y="-670"/>
</cld-image>

  </div>
</template>
<script>
export default {
  name: "TheResumeTemplate",
  props: {
    userData: { 
      type: Object, 
      required: true 
    }
  },
}
</script>

在上面,我们添加了一个props,该props将在TheDashboardBody.vue中填充其值。我们还希望像我们想要的那样使用Cloudinary的转换功能。
可以在GitHub Gist here中找到云CV模板的完整实现。

此时,我们的应用程序看起来如下:

Final application

结论

本文讨论使用Cloudinary和XATA生成简历。云用于图像转换,而我们使用XATA进行身份验证。

资源