Skip to main content

Adding Extension Features

You are reading an outdated document

Get the latest developer guides on Fynd Partners Help

Previously, you created a new extension with FDK CLI. You're now ready to start building your extension. In this document, you'll accomplish a series of tasks to add some specific functionality to your extension. Your final extension will be simple, but you’ll learn where to find resources to build more complex features on your own.


Requirements


Get Applications

QG1


<template>
<div class="groot-landing-page">
<div class="groot-saleschannel-title">Sales Channel</div>

<loader v-if="pageLoading"></loader>
<div v-else class="content">
<nitrozen-input
type="search"
placeholder="Search Sales Channels"
:showSearchIcon="true"
class="application-list"
@input="searchApplication"
></nitrozen-input>

<div class="groot-sales-channels-container">
<div
:key="application._id"
class="groot-app-box"
v-for="application of applications_list"
>
<div class="logo">
<img :src="application.logo" />
</div>
<div class="line-1">{{ application.name }}</div>
<div class="line-2">{{ application.domain.name }}</div>
<div class="groot-list-btn-cont"></div>
</div>

<div
v-if="applications_list.length % 3 == 2"
class="groot-app-box hidden"
></div>
</div>
</div>
</div>
</template>

<script>
/* File imports */
import Loader from "../components/loader.vue";
import { NitrozenInput } from "@gofynd/nitrozen-vue";

/* Service imports */
import MainService from "./../services/main-service";

export default {
name: "LandingPage",
components: {
Loader,
"nitrozen-input": NitrozenInput,
},
data() {
return {
applications_list: [],
all_applications: [],
pageLoading: false,
};
},
mounted() {
this.fetchApplications();
},
methods: {
fetchApplications() {
this.pageLoading = true;
MainService.getAllApplications()
.then(({ data }) => {
this.all_applications = data.items;
this.applications_list = data.items;
this.applications_list.map((ele) => {
(ele.text = ele.name),
(ele.value = ele._id),
(ele.image = ele.logo),
(ele.logo = ele.image && ele.image.secure_url);
});
this.pageLoading = false;
})
.catch(() => {
this.pageLoading = false;
this.$snackbar.global.showError(
"Failed to fetch the list of all applications"
);
});
},
searchApplication(searchText) {
if (!searchText) {
this.applications_list = this.all_applications.map((app) => app);
} else {
this.applications_list = this.all_applications.filter((item) => {
return item.name.toLowerCase().includes(searchText.toLowerCase());
});
}
},
},
};
</script>

<style lang="less" scoped>
.groot-landing-page {
font-family: "Inter";
position: relative;
width: 100%;
box-sizing: border-box;
max-width: 1024px;
margin: 24px auto;

.groot-saleschannel-title {
font-weight: 700;
font-size: larger;
margin-bottom: 8px;
}

.groot-sales-channels-container {
display: flex;
flex-wrap: wrap;
margin: 24px 0;
justify-content: space-between;

.groot-list-btn-cont {
display: flex;
justify-content: flex-end;

.groot-list-btn {
display: flex;
width: 40px;
height: 40px;
border: 1px solid #e4e5e6;
border-radius: 4px;
justify-content: center;
align-items: center;
cursor: pointer;
}
}
}

.groot-app-box {
width: 261px;
height: auto;
background-color: white;
border: 1px solid #e4e5e6;
padding: 24px;
border-radius: 4px;
margin-bottom: 24px;

& + .groot-app-box:nth-child(3n + 1) {
margin-left: 0;
}

.logo {
width: 48px;
height: 48px;

img {
width: 100%;
height: auto;
}
}

.line-1 {
font-weight: 600;
font-size: 16px;
line-height: 26px;
}

.line-2 {
color: #9b9b9b;
line-height: 22px;
font-size: 12px;
}
}
}

.hidden {
visibility: hidden;
}
</style>
// Main.service
"use strict";

import URLS from './endpoint.service';
import axios from 'axios';
import { getCompany } from '../helper/utils';

axios.interceptors.request.use(config => {
config.headers['x-company-id'] = getCompany();
return config;
});

const MainService = {
getAllApplications(params = {}) {
return axios.get(URLS.GET_ALL_APPLICATIONS());
},
}

export default MainService;
// endpoint.service.js

import urlJoin from "url-join";
import root from "window-or-global";
let envVars = root.env || {};

envVars.EXAMPLE_MAIN_URL = `${root.location.protocol}//${root.location.hostname}`;
if (
root &&
root.process &&
root.process.env &&
root.process.NODE_ENV == "test"
) {
envVars.EXAMPLE_MAIN_URL = 'https://api.xyz.com';
}

const Endpoints = {
GET_ALL_APPLICATIONS(){
return urlJoin(envVars.EXAMPLE_MAIN_URL, '/api/v1/applications')
}
};

export default Endpoints;

// v1.router.js

'use strict';

const express = require('express');

const router = express.Router();

// Get applications list
router.get('/applications', async function view(req, res, next) {
try {
const {
platformClient
} = req;
return res.json(await platformClient.configuration.getApplications({
pageSize: 1000,
q: JSON.stringify({"is_active": true})
}));
} catch (err) {
next(err);
}
});

module.exports = router;

// server.js

'use strict';

const express = require('express');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const path = require("path");
const healthzRouter = require("./routes/healthz.router");
const v1Router = require("./routes/v1.router");
const fdkExtension = require("./fdk");
const app = express();
app.use(cookieParser("ext.session"));
app.use(bodyParser.json({
limit: '2mb'
}));
app.get('/env.js', (req, res) => {
const commonEnvs = {
base_url: config.extension.base_url
}
res.type('application/javascript');
res.send(
`window.env = ${JSON.stringify(
commonEnvs,
null,
4
)}`
);
});
app.use("/", healthzRouter);
app.use(express.static("dist"));
app.use("/", fdkExtension.fdkHandler);
const apiRoutes = fdkExtension.apiRoutes;
apiRoutes.use('/v1', v1Router)
app.use('/api', apiRoutes);

app.get('*', (req, res) => {
res.contentType('text/html');
res.sendFile(path.join(__dirname, '../', 'dist/index.html'))
});

module.exports = app;