[Open-source] Somewhat modular application center

Recently I’ve made an application center as I want to make business with it. However, due to my current projects which sorta abandoned the project, hence I decided to make the app center open-sourced.

Here are a few reasons why you should use mine if you want text input only;

  • It’s modular, you don’t have to copy and paste the same page for each question
  • Support multiple apps in one place
  • Beautiful UI, somewhat Material Design.
  • Answer requirements, such as required question.

Bugs:

  • Debounce issue with the pages

Note:

  • This application does not come with a web API system, code your own or link it to API like Trello.
  • Text input only, no dropdown menu, or checkboxes.

If you want to test it out, join this place: https://www.roblox.com/games/4888799621/Application-center-example

That example is linked to Trello API, you can take a look of your application in https://trello.com/b/d8NAvcsS/primary

Source:
Application Center.rbxl (105.9 KB)
Everything including the textbox and button are open-source, feel free to use it for your stuff. Remember to credit me, though :slight_smile:

60 Likes

Seems pretty interesting. I love how smooth the transitions are to the next question.

1 Like

Good work man! Nice to see something for the community to use as something like this is in high demand within “roleplay” type groups…

1 Like

Looks very nice indeed. I love the transitions & the small effects there are on the buttons. Keep it up :wink:

This is very cool! However, I have a question. Would it be possible to make it so you can submit only 1 application until the other one is accepted/denied?

As I said, this is an abandoned project, do whatever you want. Though, I can try improving it if I have time.

1 Like

To make it though, you need to check whether there’s an application with the same username or userid in your database application (MongoDB, MySQL, firebase, etc)

Discord webhook will not work, I think.
The current Trello API the center uses has a GetCard thing API. However, I am pretty sure it’s broken, I recommend using the new one which is OOP

3 Likes

Well If you wanted to get it you can use a json script.
https://developer.roblox.com/en-us/api-reference/function/HttpService/GetAsync
You can get the json code from a json api or pastebin. Once the user has been accepted you can edit the pastebin or use a bot to accept it. Heres a example:

On discord: !accept app1
Bot: Updates json code on pastebin using api.
App Center: If player joins it will let them know if they have been accepted.

2 Likes

I just made you a little part of the source.

local ReplicatedStorageService = game:GetService("ReplicatedStorage")
local WebHook = "Your webhook here"
local HttpService = game:GetService("HttpService")
local Chat = game:GetService("Chat")
local URL_PASTEBIN_NEW_PASTE = "https://pastebin.com/api/api_post.php"

local GroupId = 5572964

local function Beautify(Table, User)
	local String = ""
	
	for i,v in pairs(Table.Questions) do
		String = String .. "\n" .. v .. "\n Answer: " .. Chat:FilterStringAsync(Table.Responses[i], User, User)
	end
	print(String)
	return String
end

ReplicatedStorageService:WaitForChild("AppSubmit").OnServerEvent:Connect(function(Player, AppData, ArgListID)
local Content = 
	{
		["username"] = "New application",
		["content"] = (Player.Name.. " Rank in group: " .. tostring(1) .. " \n Profile link: https://www.roblox.com/users/" .. tostring(Player.UserId) .. "/profile/ \n Application: \n" .. Beautify(AppData, Player))
	}
	local dataFields = {
	-- Pastebin API developer key from
	-- https://pastebin.com/api#1
	["api_dev_key"] = "FILL THIS WITH YOUR API DEVELOPER KEY";    
	
	["api_option"] = "paste";                                -- keep as "paste"
	["api_paste_name"] = "HttpService:PostAsync";            -- paste name
	["api_paste_code"] = "Hello, world";                     -- paste content
	["api_paste_format"] = "text";                            -- paste format
	["api_paste_expire_date"] = "10M";                       -- expire date        
	["api_paste_private"] = "0";                             -- 0=public, 1=unlisted, 2=private
	["api_user_key"] = "";                                   -- user key, if blank post as guest
}
 
-- The pastebin API uses a URL encoded string for post data
-- Other APIs might use JSON, XML or some other format
local data = ""
for k, v in pairs(dataFields) do
	data = data .. ("&%s=%s"):format(
		HttpService:UrlEncode(k),
		HttpService:UrlEncode(v)
	)
end
data = data:sub(2) -- Remove the first &
 
-- Here's the data we're sending
print(data)
 
-- Make the request
local response = HttpService:PostAsync(URL_PASTEBIN_NEW_PASTE, data, Enum.HttpContentType.ApplicationUrlEncoded, false)
-- The response will be the URL to the new paste (or an error string if something was wrong)
print(response)
HttpService:PostAsync(WebHook, HttpService:JSONEncode(Content))
wait(2)
HttpService:PostAsync(WebHook, HttpService:JSONEncode(data))
	ReplicatedStorageService:WaitForChild("AppSubmit"):FireClient(Player, "Success")
end)
1 Like

You suprise me a lot!

Again, Keep up the awesome work!

Hi lol, I’m here to update this topic again just for fun. So I made a little change to the main module script because I… added an option to open or close the app.

    local module = {}




module.App = {
	["AppTitle"] = "Application1";
	["ListId"] = "Application1",
	["Open"] = false,
	["Questions"] = {
		[1] = {
			["Question"] = "Who are you?",
			["LeaveBlank"] = false
		};
		[2] = {
			["Question"] = "Who are you? again",
			["LeaveBlank"] = false
		};
		
		[3] = {
			["Question"] = "lol",
			["LeaveBlank"] = true
		}
		
		
		
	};
	
	
	["Submitted"] = "You've submitted your application, please wait for us to read your applications"
}

return module

When the open value is set to false it will not allow the app to be used or clicked on.

https://gyazo.com/b000fd281d4642dc5e79b541ee1959b2

One of the other things I did was to make a datastore for your AppID. Yep… there’s an AppID now. So when a player creates a new application it will send it to a discord server, yes, I did remake the sender part. The AppID is basically a Pastebin code. I used a bot to trigger the better-pastebin api which uses node.js, Sadly, It did not work. The AppID can also be used to accept or to not accept the application. Now how will the player know once they get accepted? Well, if they are in the discord server and verified they will be pinged with there username. The other option is for them to join the application center two or one days later to check the status… Wait a min… I didn’t get to that part. Ah yes, I added a status checker that reads the pastetID
image

The test is the title of the app center.

Overall I changed mostly everything in this app center and redid the scripting in it.

Heres the changes to the scripts:

MainModule:

local module = {}

module.Config = {
	["AppName"] = game.Lighting.AppName.Value;
	["Emblem"] = game.Lighting.Logo.Value;
	
	
	-- Format: script.App Example: script.App1, script.App2, script.App3(No comma if 
--thats the last app.)
	["App"] = {
		script.App,
		script.App2,
		script.App3
	}
}

return module

App:

local module = {}




module.App = {
	["AppTitle"] = "Application1";
	["ListId"] = "Application1",
	["Open"] = false,
	["Questions"] = {
		[1] = {
			["Question"] = "Who are you?",
			["LeaveBlank"] = false
		};
		[2] = {
			["Question"] = "Who are you? again",
			["LeaveBlank"] = false
		};
		
		[3] = {
			["Question"] = "lol",
			["LeaveBlank"] = true
		}
		
		
		
	};
	
	
	["Submitted"] = "You've submitted your application, please wait for us to read your applications"
}

return module

AppApi(Or the sender)

local ReplicatedStorageService = game:GetService("ReplicatedStorage")
----------------------------------CHANGE WEBHOOK TO YOUR WEBHOOK ON DISCORD------------------------------------------------------------------------------|
---------------------------------------------------------------------------------------------------------------------------------------------------------|
local WebHook = "No no no :)"   
local GroupId = 5455842 -- Leave it at 0 if this app center is not in a group or for a group
---------------------------------------------------------------------------------------------------------------------------------------------------------|

---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------DO NOT TOUCH BEBLOW-------------------------------------------------------------------------------------------------



local HttpService = game:GetService("HttpService")
local Chat = game:GetService("Chat")
local URL_PASTEBIN_NEW_PASTE = "https://pastebin.com/api/api_post.php"



local function Beautify(Table, User)
	local String = ""
	
	for i,v in pairs(Table.Questions) do
		String = String .. "\n" .. v .. "\n Answer: " .. Chat:FilterStringAsync(Table.Responses[i], User, User)
	end
	print(String)
	return String
end

ReplicatedStorageService:WaitForChild("AppSubmit").OnServerEvent:Connect(function(Player, AppData, ArgListID)

	local dataFields = {
	-- Pastebin API developer key from
	-- https://pastebin.com/api#1
	["api_dev_key"] = "deleted";    
	
	["api_option"] = "paste";                                -- keep as "paste"
	["api_paste_name"] = Player.Name.."'s Application Status";            -- paste name
	["api_paste_code"] = "Pending";                     -- paste content
	["api_paste_format"] = "text";                            -- paste format
	["api_paste_expire_date"] = "N";                       -- expire date        
	["api_paste_private"] = "0";                             -- 0=public, 1=unlisted, 2=private
	["api_user_key"] = "removed";                             -- user key, if blank post as guest
}
 
-- The pastebin API uses a URL encoded string for post data
-- Other APIs might use JSON, XML or some other format
local data = ""
for k, v in pairs(dataFields) do
	data = data .. ("&%s=%s"):format(
		HttpService:UrlEncode(k),
		HttpService:UrlEncode(v)
	)

data = data:sub(2) -- Remove the first &
 end
local response = HttpService:PostAsync(URL_PASTEBIN_NEW_PASTE, data, Enum.HttpContentType.ApplicationUrlEncoded, false)
print(data)

response = response:sub(22)
local data = 
	{
		["content"] = "",
		["embeds"] = {{
			["title"] = "App ID: "..response.."                                           Username: "..Player.Name,
			["description"] = ("Rank in group: " .. Player:GetRoleInGroup(GroupId) .. " \n Profile link: https://www.roblox.com/users/" .. tostring(Player.UserId) .. "/profile/ \n Application: \n" .. Beautify(AppData, Player)),
			["type"] = "rich",
			["color"] = tonumber(0xffffff),["fields"] = {
				{
					["name"] = "CenterBlox",
					["value"] = "If you cannot accept applications, Please let your group HR do it. Paste App ID into the main app site to approve or not approve. If you can accept say !link to get the link!",
					["inline"] = true
				},
				}
			
		}}
	}
Player.leaderstats.YourAppCode.Value = response
HttpService:PostAsync(WebHook, HttpService:JSONEncode(data))
ReplicatedStorageService:WaitForChild("AppSubmit"):FireClient(Player, "Success")



	
	
end)

SOME ADDED SCRIPTS?!?!?!

Datastore:

game.Players.PlayerRemoving:connect(function(player)
	local datastore = game:GetService("DataStoreService"):GetDataStore(player.Name.."Stats")

local statstorage = player:FindFirstChild("leaderstats"):GetChildren()
for i =  1, #statstorage do
	datastore:SetAsync(statstorage[i].Name, statstorage[i].Value)
	print("saved data number "..i)
	
end
print("Stats successfully saved")	
end)



game.Players.PlayerAdded:connect(function(player)
		local datastore = game:GetService("DataStoreService"):GetDataStore(player.Name.."Stats")
	
	player:WaitForChild("leaderstats")
	wait(1)
	local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")

	local stats = player:FindFirstChild("leaderstats"):GetChildren()
	for i = 1, #stats do	
		stats[i].Value = datastore:GetAsync(stats[i].Name)
		local paste = HttpService:GetAsync("http://pastebin.com/raw/="..player.leaderstats.YourAppCode.Value)
		wait(2)
	print("stat numba "..i.." has been found")
	print(paste)
	player.PlayerGui.Core.Elements.Background.Container.Home.Emblem.Semi2.Text = "Here to check on your application status? Your application status is: "..paste
	if 
		player.PlayerGui.Core.Elements.Background.Container.Home.Emblem.Semi2.Text == "Here to check on your application status? Your application status is: Passed"
		then
			player.leaderstats.YourAppCode.Value = ""
		end
	while true do
		wait(3)
		
	if 
		player.leaderstats.YourAppCode.Value == ""
		then
			player.PlayerGui.Core.Elements.Background.Container.Home.Emblem.Semi2.Text = "You do not have any pending applications! Create one or see if you passed a application!"
			print("I don't see any apps")
		end
end	
		end
		 
			
end)

leaderstats:

function onPlayerEntered(newPlayer)
	wait(.5)
	local stats = Instance.new("IntValue")
	stats.Name = "leaderstats"

	local score = Instance.new("StringValue")
	
	score.Name = "YourAppCode"
	score.Value = ""
	score.Parent = stats	
	stats.Parent = newPlayer
	
	end

game.Players.ChildAdded:connect(onPlayerEntered)

I hope you like it and I’ll make sure to keep on updating!

3 Likes

I am very confused on how to set up the trello… I can edit the application settings perfectly, but the trello is where I need help. If you can help me with this it would be great.

The trello api is pretty old and pretty messy, you really need some programming knowledge to know what you need to do with the API, yikes.

I’ll try to replace the current one in the app center with the new one, which is OOP.

Like nakogls said, The Trello API is pretty old. You should use my part of the application center script that I rewrote until he updates the trello. So just get rid of the trellomodule and replace the AppScript with this code:

local ReplicatedStorageService = game:GetService("ReplicatedStorage")
----------------------------------CHANGE WEBHOOK TO YOUR WEBHOOK ON DISCORD------------------------------------------------------------------------------|
---------------------------------------------------------------------------------------------------------------------------------------------------------|
local WebHook = "No no no :)"   
local GroupId = 5455842 -- Leave it at 0 if this app center is not in a group or for a group
---------------------------------------------------------------------------------------------------------------------------------------------------------|

---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------DO NOT TOUCH BEBLOW-------------------------------------------------------------------------------------------------



local HttpService = game:GetService("HttpService")
local Chat = game:GetService("Chat")
local URL_PASTEBIN_NEW_PASTE = "https://pastebin.com/api/api_post.php"



local function Beautify(Table, User)
	local String = ""
	
	for i,v in pairs(Table.Questions) do
		String = String .. "\n" .. v .. "\n Answer: " .. Chat:FilterStringAsync(Table.Responses[i], User, User)
	end
	print(String)
	return String
end

ReplicatedStorageService:WaitForChild("AppSubmit").OnServerEvent:Connect(function(Player, AppData, ArgListID)

	local dataFields = {
	-- Pastebin API developer key from
	-- https://pastebin.com/api#1
	["api_dev_key"] = "deleted";    
	
	["api_option"] = "paste";                                -- keep as "paste"
	["api_paste_name"] = Player.Name.."'s Application Status";            -- paste name
	["api_paste_code"] = "Pending";                     -- paste content
	["api_paste_format"] = "text";                            -- paste format
	["api_paste_expire_date"] = "N";                       -- expire date        
	["api_paste_private"] = "0";                             -- 0=public, 1=unlisted, 2=private
	["api_user_key"] = "removed";                             -- user key, if blank post as guest
}
 
-- The pastebin API uses a URL encoded string for post data
-- Other APIs might use JSON, XML or some other format
local data = ""
for k, v in pairs(dataFields) do
	data = data .. ("&%s=%s"):format(
		HttpService:UrlEncode(k),
		HttpService:UrlEncode(v)
	)

data = data:sub(2) -- Remove the first &
 end
local response = HttpService:PostAsync(URL_PASTEBIN_NEW_PASTE, data, Enum.HttpContentType.ApplicationUrlEncoded, false)
print(data)

response = response:sub(22)
local data = 
	{
		["content"] = "",
		["embeds"] = {{
			["title"] = "App ID: "..response.."                                           Username: "..Player.Name,
			["description"] = ("Rank in group: " .. Player:GetRoleInGroup(GroupId) .. " \n Profile link: https://www.roblox.com/users/" .. tostring(Player.UserId) .. "/profile/ \n Application: \n" .. Beautify(AppData, Player)),
			["type"] = "rich",
			["color"] = tonumber(0xffffff),["fields"] = {
				{
					["name"] = "CenterBlox",
					["value"] = "If you cannot accept applications, Please let your group HR do it. Paste App ID into the main app site to approve or not approve. If you can accept say !link to get the link!",
					["inline"] = true
				},
				}
			
		}}
	}
Player.leaderstats.YourAppCode.Value = response
HttpService:PostAsync(WebHook, HttpService:JSONEncode(data))
ReplicatedStorageService:WaitForChild("AppSubmit"):FireClient(Player, "Success")



	
	
end)

Just make sure you have these two scripts:

Datastore(required)

game.Players.PlayerRemoving:connect(function(player)
	local datastore = game:GetService("DataStoreService"):GetDataStore(player.Name.."Stats")

local statstorage = player:FindFirstChild("leaderstats"):GetChildren()
for i =  1, #statstorage do
	datastore:SetAsync(statstorage[i].Name, statstorage[i].Value)
	print("saved data number "..i)
	
end
print("Stats successfully saved")	
end)



    game.Players.PlayerAdded:connect(function(player)
    		local datastore = game:GetService("DataStoreService"):GetDataStore(player.Name.."Stats")
    	
    	player:WaitForChild("leaderstats")
    	wait(1)
    	local Players = game:GetService("Players")
    local HttpService = game:GetService("HttpService")

    	local stats = player:FindFirstChild("leaderstats"):GetChildren()
    	for i = 1, #stats do	
    		stats[i].Value = datastore:GetAsync(stats[i].Name)
    		local paste = HttpService:GetAsync("http://pastebin.com/raw/="..player.leaderstats.YourAppCode.Value)
    		wait(2)
    	print("stat numba "..i.." has been found")
    	print(paste)
    	player.PlayerGui.Core.Elements.Background.Container.Home.Emblem.Semi2.Text = "Here to check on your application status? Your application status is: "..paste
    	if 
    		player.PlayerGui.Core.Elements.Background.Container.Home.Emblem.Semi2.Text == "Here to check on your application status? Your application status is: Passed"
    		then
    			player.leaderstats.YourAppCode.Value = ""
    		end
    	while true do
    		wait(3)
    		
    	if 
    		player.leaderstats.YourAppCode.Value == ""
    		then
    			player.PlayerGui.Core.Elements.Background.Container.Home.Emblem.Semi2.Text = "You do not have any pending applications! Create one or see if you passed a application!"
    			print("I don't see any apps")
    		end
    end	
    		end
    		 
    			
    end)

leaderstats(required)

function onPlayerEntered(newPlayer)
	wait(.5)
	local stats = Instance.new("IntValue")
	stats.Name = "leaderstats"

	local score = Instance.new("StringValue")
	
	score.Name = "YourAppCode"
	score.Value = ""
	score.Parent = stats	
	stats.Parent = newPlayer
	
	end

game.Players.ChildAdded:connect(onPlayerEntered)

The other thing I forgot to post was the slightly new core script inside the GUI

Since I can’t like copy changes from a gui over to a textbox here is the rbxm for the Core GUI

Core.rbxm (18.4 KB)

If you don’t understand how to add the scripts correctly then you can download the full game here that I did over(Its the same but with my api and other stuff)
Application Center(REWRITE).rbxl (96.3 KB)

Hope this will help!

1 Like

Thank you so much! As this will be very helpful in the future.

1 Like

Another Update? Here we go again…

Hello Im going a quick update since I haven’t posted in 8 days on this thread.

Yes… How far have I come? Idk a long way. Ill be releasing the node.js bot source on glitch. This is not as good as myCenter but… It will be soon. I hope I can work for them one day.

Beautiful! It’s really smooth!

This is very helpful for me Thank you for sharing this.



I am back.

4 Likes

This is gonna be really useful for my group! Thanks! :pray:

1 Like