diff --git a/resources/js/config.js b/resources/js/config.js
index ee2b22ee5..b2d577b89 100644
--- a/resources/js/config.js
+++ b/resources/js/config.js
@@ -1 +1 @@
-var __DOCS_CONFIG__ = {"id":"Mc84HrDBLD7+Hmbk163BWruvuVY2gXSs90e","key":"WkZuLxS7XbFYMCxQrzBq7U51EVN1Zc9bpDr2bZXIeXo.pTUAaWcBZvAg+9LeGZy0pyD4YL/ftM0cYhO3ZSJixWLAQXr+0WBAQtVJua7r227b119a5/a+QcY1y4z4Y6UbWQ.8236","base":"/","host":"docs.chiefonboarding.com","version":"1.0.0","useRelativePaths":true,"documentName":"index.html","appendDocumentName":false,"trailingSlash":true,"preloadSearch":false,"cacheBustingToken":"3.5.0.752017923197","cacheBustingStrategy":"query","sidebarFilterPlaceholder":"Filter","toolbarFilterPlaceholder":"Filter","showSidebarFilter":true,"filterNotFoundMsg":"No member names found containing the query \"{query}\"","maxHistoryItems":15,"homeIcon":"
","access":[{"value":"public","label":"Public"},{"value":"protected","label":"Protected"}],"toolbarLinks":[{"id":"fields","label":"Fields"},{"id":"properties","label":"Properties"},{"id":"methods","label":"Methods"},{"id":"events","label":"Events"}],"sidebar":[{"n":"/","l":"What's Chief​Onboarding?"},{"n":"howto","l":"How to / Demo"},{"n":"deployment","l":"Deployment"},{"n":"development","l":"Development"},{"n":"architecture","l":"Architecture"},{"n":"integrations","l":"Integrations / Webhooks (Beta)"},{"n":"api","l":"API"},{"n":"changelog","l":"Changelog"}],"search":{"mode":0,"minChars":2,"maxResults":20,"placeholder":"Search","hotkeys":["k"],"noResultsFoundMsg":"Sorry, no results found.","recognizeLanguages":true,"languages":[0],"preload":false},"resources":{"History_Title_Label":"History","History_ClearLink_Label":"Clear","History_NoHistory_Label":"No history items","API_AccessFilter_Label":"Access","API_ParameterSection_Label":"PARAMETERS","API_SignatureSection_Label":"SIGNATURE","API_CopyHint_Label":"Copy","API_CopyNameHint_Label":"Copy name","API_CopyLinkHint_Label":"Copy link","API_CopiedAckHint_Label":"Copied!","API_MoreOverloads_Label":"more","API_MoreDropdownItems_Label":"More","API_OptionalParameter_Label":"optional","API_DefaultParameterValue_Label":"Default value","API_InheritedFilter_Label":"Inherited","Search_Input_Placeholder":"Search","Toc_Contents_Label":"Contents","Toc_RelatedClasses_Label":"Related Classes","History_JustNowTime_Label":"just now","History_AgoTime_Label":"ago","History_YearTime_Label":"y","History_MonthTime_Label":"mo","History_DayTime_Label":"d","History_HourTime_Label":"h","History_MinuteTime_Label":"m","History_SecondTime_Label":"s"}};
+var __DOCS_CONFIG__ = {"id":"ohQPclXWzUPrc7163a/gi1wqWXuKJe3IkEb","key":"NgC5Q6nOMJQ4O+16pDO4mFLjIFL+Rm0vEg+0RvMEicY.PCB3g2XDOpSV20xx0wQ3XxVNEJ5B/tTVna5uI4mlHxkvZRkk7w6FOA/qMO0LREJQ8TAiRbjJMMgkfb9Nl2SXQQ.8286","base":"/","host":"docs.chiefonboarding.com","version":"1.0.0","useRelativePaths":true,"documentName":"index.html","appendDocumentName":false,"trailingSlash":true,"preloadSearch":false,"cacheBustingToken":"3.5.0.752636453443","cacheBustingStrategy":"query","sidebarFilterPlaceholder":"Filter","toolbarFilterPlaceholder":"Filter","showSidebarFilter":true,"filterNotFoundMsg":"No member names found containing the query \"{query}\"","maxHistoryItems":15,"homeIcon":"
","access":[{"value":"public","label":"Public"},{"value":"protected","label":"Protected"}],"toolbarLinks":[{"id":"fields","label":"Fields"},{"id":"properties","label":"Properties"},{"id":"methods","label":"Methods"},{"id":"events","label":"Events"}],"sidebar":[{"n":"/","l":"What's Chief​Onboarding?"},{"n":"howto","l":"How to / Demo"},{"n":"deployment","l":"Deployment"},{"n":"development","l":"Development"},{"n":"architecture","l":"Architecture"},{"n":"integrations","l":"Integrations / Webhooks (Beta)"},{"n":"api","l":"API"},{"n":"changelog","l":"Changelog"}],"search":{"mode":0,"minChars":2,"maxResults":20,"placeholder":"Search","hotkeys":["k"],"noResultsFoundMsg":"Sorry, no results found.","recognizeLanguages":true,"languages":[0],"preload":false},"resources":{"History_Title_Label":"History","History_ClearLink_Label":"Clear","History_NoHistory_Label":"No history items","API_AccessFilter_Label":"Access","API_ParameterSection_Label":"PARAMETERS","API_SignatureSection_Label":"SIGNATURE","API_CopyHint_Label":"Copy","API_CopyNameHint_Label":"Copy name","API_CopyLinkHint_Label":"Copy link","API_CopiedAckHint_Label":"Copied!","API_MoreOverloads_Label":"more","API_MoreDropdownItems_Label":"More","API_OptionalParameter_Label":"optional","API_DefaultParameterValue_Label":"Default value","API_InheritedFilter_Label":"Inherited","Search_Input_Placeholder":"Search","Toc_Contents_Label":"Contents","Toc_RelatedClasses_Label":"Related Classes","History_JustNowTime_Label":"just now","History_AgoTime_Label":"ago","History_YearTime_Label":"y","History_MonthTime_Label":"mo","History_DayTime_Label":"d","History_HourTime_Label":"h","History_MinuteTime_Label":"m","History_SecondTime_Label":"s"}};
diff --git a/resources/js/search.json b/resources/js/search.json
index c548cef1c..a1cfd9877 100644
--- a/resources/js/search.json
+++ b/resources/js/search.json
@@ -1 +1 @@
-[[{"i":"whats-chiefonboarding","l":"What's ChiefOnboarding?","p":["In one sentence, ChiefOnboarding is an open-source remote-first employee onboarding platform that helps you streamline the employee experience for both the new hire and you through Slack or the web portal.","With ChiefOnboarding you can create generic new hire timelines and apply them to specific new hires. Timelines are designed in a way that it will reduce the overwhelming feeling that a new hire often gets on their first few days and increases overall quality due to consistency.","Let's start at the beginning. Your new hire just said: \"Yeah! I want to work for you\" and you both signed the contracts. Up next, you need to make sure that your new hire knows things like the dress code, when they should start and what to expect from their first few days. That's often called pre-boarding.","With our pre-boarding module, you can create several pages with information, pictures, files, lists and so on with everything that your new hire needs to know. You can even add custom forms that will allow you to get some information from your new hire before they start. How about asking them for their favorite snack and adding that to their goodie pack to surprise them?","Oh... but someone needs to make that goodie pack, right? That's why we created our \"tasks\" module. In the timeline you can add tasks for your colleagues. Those are automatically created and colleagues will be notified of them. Colleagues are able to leave comments and check them off. They can even collaborate with others on a shared task.","In the meantime, our Slack bot will send your team a message letting them know that someone is starting very soon. Your colleagues will be able to leave a custom welcome message, which will show up in the new hire's preboarding pages. Talking about keeping it personal!","It's a few days before the new hire starts. It's probably a good idea to give the buddy and manager a quick heads-up about the new hire starting soon - better be safe than sorry. Add a custom Slack/Email/Text message in the timeline so they will be reminded on time.","Oh no, you still need to set up their user accounts (Slack, Google, Asana etc) to give them access to the things they will need. Your IT department is already clocking in overtime... Our account provisioning module will take care of that for you! Add the integrations to your timeline on the day you want and let the platform create the accounts for them.","It's the new hire's first day and your new hire gets to meet a lot of people in your Slack team. To avoid any awkward conversations, your new hire can look into the colleagues directory to see who does what. Even better yet, you can send colleague introductions directly to your new hire. This is great for introducing their direct coworkers.","There are some tasks that every new hire needs to complete, right? You can easily create those todo items and follow up on those or remind them if they are late on one (this can also be automated by the way). Got a quick assessment for them to complete? Throw it in a to do item and have them complete it!","Adding too many to do items could be a bit demotivating. Especially if they are mostly boring things that just need to get done. You can obviously spread them over the first few days/weeks, but that might not be enough. We hear you... How about rewarding them with a badge? Throw a condition in the timeline that waits for a few to do items to be completed and then sends them a custom message with a reward. As easy as that.","Over the next few weeks, they will have to learn a lot of things. General things like how to request a holiday or how to collect their paycheck come to mind. With our \"Resources\" module, you can easily create small wiki's with all the information they need. You can let them go through the resource by themselves, or convert it to a course to validate that they actually read through it all with questionaires.","Those timelines are extremely flexible. We understand that every company is different and that you need a custom approach to your onboarding plan."]},{"l":"Privacy","p":["We care about your privacy. ChiefOnboarding does not contain any weird or creepy trackers and you can even host it on your own servers if you really want full control over it. You might find that some of the integrations require quite a lot of permissions from a third party. That kind of info is stored in encrypted fields and I want to emphasise that ChiefOnboarding does not ping home, ever! We will never receive any information from your server.","We can collect error logs for users who use our servers. This will ensure quick bug fixes and therefore improve stability of the platform. This is always on an opt-in basis - it's disabled by default and we ask for permission."]},{"l":"Support","p":["Over the past 1,5 years (Sept 2020 - August 2022), we have had an average response time to questions of 1 hour and an average response time of 2 hours for bug fixes (actually fixing the bug, not just acknowledging the bug report). While those aren't official SLAs, we do our best to keep those averages as low as they are. Email support is only part of our paid plans, users hosting their own copy will have to fallback to Github issues (and it takes more time to get back to you - paying customers are always in the priority queue). With the support and managed package, you get the best of both worlds: the transparancy of open source software with the fast support of a premium software package.","Helpful links:","ChiefOnboarding repo: https://github.com/chiefonboarding/ChiefOnboarding","Pricing: https://chiefonboarding.com/pricing"]}],[{"i":"how-to--demo","l":"How to / Demo","p":["At ChiefOnboarding, we currently don't do demos with potential customers. Demos take a lot of time and are quite similar between potential customers. You all come with the same goal, right? Improving your onboarding process.","Underneath, you will basically find the transcript of a demo. You will get to see most of the features that our software provides and you can easily come back to it, if you want to look something up again. At the same time, we can keep working on features that you want.","As always: if you have a question, feel free to send us an email- we are fast at replying (often within an hour)."]},{"l":"Sequences","p":["At ChiefOnboarding, we base everything around sequences. Sequences are basically timelines which will map out the new hire's onboarding path. It looks like this:","Let's break it down a bit:","Sequences consist of blocks. We currently have 3 types of blocks:","General blocks","Block before the new hire starts","Block after the new hire has started","Block based on the completion of a to do item","Unconditioned block"]},{"l":"The general blocks","p":["There are three types of general blocks that you can choose from. You can create a block that triggers before the new hire starts. You could use this to create tasks (we will get to this later) for colleagues for things they need to do or send some emails/slack/text messages.","The second type of general blocks are the ones that start after the new hire starts. These are marked in workdays, so it doesn't really matter if your new hire starts on a Monday or Thursday - ChiefOnboarding will skip the weekends and not bother the new hire on those days. Example: Monday is workday 1, next week Monday is then day 6. You can add a bunch more in these types of blocks (which we will get into in a bit). We will notify the new hire of any newly added things - you can disable this if you don't want that.","All of the above blocks trigger at 8 AM in the new hire's timezone. Yes, ChiefOnboarding is totally remote friendly, we support multiple time zones and multiple languages.","The third type of general block is a special one. You can have things happen based on a to do item. We will get into to do items in a bit, but basically what this means is that you can wait for your new hire to complete a to do item and then it will trigger to create a new to do item for the new hire or perhaps send a message to a colleague. The possibilities are endless."]},{"l":"The unconditioned block","p":["You can only add one of these and you can add things in here that are automatically added to the new hire when you add the sequence to your new hire. You could add some random stuff in here that your new hire might need or that they need right from the start. Think of some policies and some default to do items.","Also often used to add preboarding pages that your new hire will be able to see BEFORE they join the company. A pre-boarding page basically looks like this:","preboarding edit","And you can preview it with the preview button, it will look like this:","preboarding view","You might have noticed the little part at the bottom that says \"Form options\". You can actually build a custom form where you can allow your new hire to send some information back to you. Perhaps you want to know what their favorite snack is."]},{"l":"Templates","p":["So what could we put in these blocks? We have created a few different types of templates that you could add in these. You could create those templates before you start to create the sequence, but you can also just add items as you go."]},{"l":"To do items","p":["To do items look like this (for you):","todo edit","Let's break it down a bit more.","I think the title speaks for itself: it will be displayed to the new hire with that.","The Due on workday field will allow you to add a workday on when the tasks needs to be completed. New hire's will get a notification of that in Slack/Webportal. Remember: this is workdays, not calendar days. If Monday is day 1, then next week Monday is day 6!","Then we have the Tags part. This is just a means of identification for yourself and other staff members. Totally optionally, but just something for you to separate tasks that have the same name. New hires will never get to see the tags.","The content is basically a WYSIWYG editor that allows you to add various things. Such as headers, lists, files and images. You can even create forms in these if you would like to get some info back from the new hire.","At the very bottom, you have a quick check box (only available with Slack integration), which is currently checked. This means that the answers from the new hire will be sent back to the Slack channel that you specify there. It's best to make the new hire aware of this, so they don't add anything they wouldn't want to share with the rest of the team. This feature is perfect for when you want to let your new hire introduce to the team with a default format."]},{"l":"Resource items","p":["Resource items are meant to inform your new hire. Think of general procedures, how to use specific tools etc. Resources look like this (for you):","resources edit","We already covered the title, tags and content part - they are the same as with the todo/preboarding items. Something new here is the 'Chapters' part. The name already gives it away, you can create chapters in these resources. This comes in handy when you want to split information a bit more (in the event that headers aren't enough). By default, you can't really check if the new hire indeed read/understood what was in the chapter. To solve that, you could turn the resource into a course (see the switch 'Is a course item'). If you enable that, your new hire will have to go through the resource chapter by chapter. You could also add questions in between the chapters, so you can check their knowledge. You will be able to see the answer that they filled in on your side. The chapter with a question mark icon before it are these test. They can only consist of multiple choice questions. You can also pick or create a category to separate the multiple resources for your new hire."]},{"l":"Introduction items","p":["Your new hire is new to the company and they barely know anyone. Perhaps they know a few people through the interviews, but that's most likely it. Introduction items are items that introduce your colleagues to your new hire. They look like this for you:","introduction edit","On the right side, you have an example of how it looks for your new hire (in the webportal). Please note that items within the curly brackets, those will be replaced with the new hire's first name. This goes for most fields in the software (including content and title items). You can use these placeholders (within curly brackets):","first_name: new hire's first name","last_name: new hire's last name","email: new hire's email address","position: new hire's position","department: new hire's department (if any)","buddy: new hire's buddy's full name","buddy_email: new hire's buddy's email address","manager: new hire's manager's full name","manager_email: new hire's manager's email address"]},{"l":"Badge items","p":["Badges are a way to keep your new hire motivated. You can't really do much with a badge, it's just there to give your new hire that extra bit of positivity between going through all the boring tasks they need to complete.","badge edit"]},{"l":"Admin to do items","p":["Sometimes, you or any of your colleagues need to do something for your new hire as well. With these items, you can automatically create a to do item for someone. You can assign it to someone and you can also notify someone else of this.","admin todo edit","They will get a notification of this through Slack or email."]},{"i":"textslackemail-messages","l":"Text/Slack/Email messages","p":["I am going over those all at once as they all have the same purpose: Sending a one-off message to someone. This 'someone' could be the new hire themselves, the manager or buddy assigned to the new hire or some random person that you can pick yourself (or in the case of Slack; a channel is possible as well).","Here is an example of an email message:","admin todo edit","Here is how the bottom part of our sequence looks like now. Now, this is only a really small sequence and you can make those as large as you want. You could also stack them - adding multiple sequences to one new hire.","sequence end"]},{"l":"People","p":["Everyone that is in ChiefOnboarding is listed under 'People' -> 'Employees'. Those include all new hires, administrators, people with no access to the dashboard and people that have limited access to the dashboard. Let's break it down a bit more:"]},{"l":"Administrators","p":["Administrators are people that have full control over the dashboard. They can create new hires, remove them, create sequences and templates and so on. You can create as many as you would like."]},{"l":"Administrators with limited access","p":["Optionally, you can add people with limited access. They have access to their new hire's (being the manager), the templates/sequences and their admin to do items. They will NOT have access to settings items."]},{"l":"Employees","p":["Employees are basically empty accounts. They don't do much by default. They will show up on the colleagues page, but that's basically it. You can import them from Slack to quickly have them all listed here.","If you want, you can assign resources to these people and then they will be able to use the Slack bot and online webportal too look into these. Resources don't have to be just for new hires - they can be useful for long time employees as well. The colleagues page will be accessible for them too then."]},{"l":"New hires","p":["You can create new hires in three different ways:","Filling in the form in the dashboard","Using the API","Automatically adding new hires when they join Slack (with or without manual approval)"]},{"l":"Filling in the form","p":["new new hire","Let's look at each form field:","First name: The new hire's first name","Last name: The new hire's last name","Email: This is the email address from the new hire - the corporate one","Phone number: This is the new hire's phone number (used to send sequence text messages to or preboarding page invitations)","Position: This is the new hire's position or title. Only used for introducing the new hire","New hire's starting date: The day the new hire starts working.","What can you share about this new hire?: This is the message that will be send to the team to introduce this new hire. Colleagues will be able to leave a personal welcome message if they want to.","New hire's timezone: Mainly used by the slack bot, but also for sending some emails. No one likes getting messages in the middle of the night.","Language: We currently support English, Dutch, French, German, Turkish, Portuguese, Spanish and Japanese. Please note that language support is still under development - some parts might not be translated properly yet.","New hire's buddy: This is the new hire's buddy, you can use this field for sending messages in the sequence.","New hire's manager: This is the new hire's manager, you can use this field for sending messages in the sequence.","Sequences: This is the part where you can assign your pre-made sequences to the new hire. If some items won't be triggered (because you created the new hire later than the first item in the sequence), then you will git a popup asking if you want to trigger those items immediately.","Once created, you can choose to send the new hire's preboarding email. This one is not sent automatically, as you might want to make changes before you send it (this will be implemented as part of the sequences later on though)."]},{"l":"Using the API","p":["Please go to the API doc page for instructions on how to set this up."]},{"i":"automatically-adding-new-hires-when-they-join-slack-with-or-without-manual-approval","l":"Automatically adding new hires when they join Slack (with or without manual approval)","p":["In the settings, there is now the option to enable 'automatic new hire creation from people joining Slack'. When a new hire joins Slack, ChiefOnboarding will get notified and it will automatically create a new hire account for them. It will also assign one or more default sequences to the new hire. No manual action is needed here - everything is automated.","Optionally, you can also enable another setting that sends you a message to manually allow/deny a new hire account. When a new hire joins Slack, you (or someone else) would get this message:","new new hire","If you click on 'Yeah!', then you will get a popup where you can choose the sequences you want to assign to them."]},{"i":"new-hires-slack-bot","l":"New hire's Slack bot","p":["An introduction in Slack will look like this:","As you can see there, they can pick any chapter they want.","Courses will look like this:","Forms work within Slack as well, with the exception of upload fields. When you use an upload field, we will redirect the new hire to the website to complete this (they don't have to login for this).","introduction slack","new new hire","Resources look like this:","slack course","slack daily reminder","slack resource","They can't skip through lessons, they will have to complete them one by one, before it's marked as done. Once a course is done, it will turn into a resource, so new hires can look through them even after they completed it.","They will be able to leave a personalized message for the new hire. This will show up on their pre-boarding pages as an extra page with all the messages from colleagues.","This is the first welcome message that is being sent to your new hire when we found the new hire in your slack team (we check every 15 minutes if there are new people in Slack, so it could take up to 15 minutes to find your new hire). You can customize this message of course to anything you like. The buttons are also optional. Along with the message, it adds the to do items that are due for that day. These are mainly to do items that are added under the 'unconditioned block' (see sequences above). Items that are added later, will be send to the new hire around 8am in the morning. The new hire will be notified for new to do items and to do items that are due (or even overdue).","todo form slack","When a new person is added, the bot will send a message to the team letting them know someone is starting soon. introduction new hire","You can customize the bot however you like. Use your own name for it and profile picture, so please ignore the current name / profile picture of the bot in the pictures below."]},{"i":"new-hires-web-portal","l":"New hire's web portal","p":["Now, most people will use the Slack integration. The web portal is more of a fallback to when a specific team in the company isn't using Slack. You can use the Slack integration standalone, but you can also use the web portal standalone. Both have all features. It's not recommended to mix them up as the Slack bot might have to do items that might have been completed already in the web portal. But, ultimately, it's up to you to decide.","The to do area looks like this:","new hire portal todo","A specific resource could look like this:","new hire portal resource","Resource that are being used as courses can contain questions and that looks like this:","new hire portal questions","You are able to view the answers in your dashboard.","There is a colleagues page that your new hires (and also colleagues that have been with you for longer) can visit to see everyone.","new hire portal colleagues"]}],[{"l":"Deployment","p":["Currently, three ways of deploying are supported out of the box. Docker, Render and Heroku.","Deploy with Docker","Deploy with Render","Deploy with Heroku","Once you have set one of them up, you will need to follow the next steps to set up storage, email, text messagea and more!"]},{"l":"Deploy with Docker","p":["You can easily deploy ChiefOnboarding with Docker (Docker-compose). Make sure that both Docker and Docker-compose are installed and your server. Please note that some of the data below contain example values and should be replaced.","Point your domain name to your IP address.","Create a folder somewhere and then add this docker-compose.yml file (change the environment variables to something that works for you!):"]},{"i":"21-caddy-based-deployment","l":"2.1 Caddy-based deployment","p":["If you don't want to have a secure connecting and want to connect over http(not secure, and you will have to change the Caddy file below), then add HTTP_INSECURE=True to your environment variables.","2.1.1 Then we need to create a Caddyfile to route the requests to the server (change the domain name, obviously):"]},{"i":"22-non-caddy-based-deployment","l":"2.2 Non-caddy-based deployment","p":["This method may make it easier to deploy on a server that is already configured with an existing web server (e.g., Nginx, Apache, etc.) You will need to install Cerbot to configure LetsEncrypt. This approach assumes that you will be configuring a reverse proxy on port 8888.","You can now run docker compose: docker-compose up. When you go to your domain name, you should see a login form where you can fill in your username and password (either from the logs, or specified yourself). There will be some demo data in there already, feel free to delete everything.","Note: if you need to do a healthcheck for your container, then you can use the url /health for that. This url is available under any IP/domain name. It will respond with a 200 status and an ok as content. The ALLOWED_HOSTS variable is ignored for that url."]},{"l":"Update docker image","p":["Please make a backup of your database before doing this.","First stop all containers: docker-compose down","Pull the new image: docker-compose pull","Start the containers: docker-compose up -d"]},{"l":"Deploy with Render","p":["You will have to login to Render or create an account there. Then, you will need to click this link to start the process: Deploy to Render","You will then need to fill in the following details:","ALLOWED_HOSTS: This needs to be the domain you want to use for the platform. Either your Render subdomain or your own subdomain. You can add multiple urls if you want to make it available with multiple urls (example: domain.example.com,domain2.example.com). Do not add the protocol ( https://) before the url. If you don't have a url, use test.chiefonboarding.com and change it later to your xxxx.onrender.com link.","Click on deploy and let it run. This will take about 10 minutes before it's ready, though it could take a few hours, so be patient please.","If you DO have a domain name:","Go to the chiefonboarding service and go to settings. Scroll down until you see the Custom domain setting. Add your domain there and configure your DNS to link to it.","If you DO NOT have a domain name:","Go to environment variables and swap the ALLOWED_HOSTS and BASE_URL with the url that has been given to you by Render. Wait for it to automatically redeploy.","That's all!"]},{"l":"Deploy with Heroku","p":["ALLOWED_HOSTS: This needs to be the domain you want to use for the platform. Either your Heroku subdomain or your own subdomain. You can add multiple urls if you want to make it available with multiple urls (example: domain.example.com,domain2.example.com). Do not add the protocol ( https://) before the url.","Click on Deploy app. You should see this when it's done (this might take a few minutes):","heroku click recheck","heroku deploy done","heroku new domain","heroku settings domain","If you are using a custom domain: go to the settings area and look for the 'domains' part:","Please note: you will need to have an account at Heroku for this to work. Hosting at Heroku is more expensive than hosting it with Docker on a VPS. We will set it up to use two Hobby Dynos (which will be $14/month). A database upgrade might be necessary later on.","SECRET_KEY: You can't change this and shouldn't. It will be generated by Heroku. It's used for signing cookies, encrypting data etc.","SSL_REDIRECT: Leave it at True. This is used to redirect all traffic from http to https.","That's all!","The app name can be anything you want (so long it is available).","Then click on 'Add domain' and enter your domain name. You will get a DNS target to point your domain name to in your DNS settings:","Under \"config vars\" you will have 5 items. Before you fill in anything: decide whether you want to use a Heroku subdomain app name.herokuapp.com or your own domain onboarding.yourcompany.com. Your own domain doesn't have to be a subdomain.","You might get a red icon now next to your domain name. It might take a bit of time to get your domain validated (DNS is often cached). Just wait for a bit and try to refresh it until it becomes green:","You will have to login to Heroku or create an account there. Then, you will need to click this link to start the process: https://heroku.com/deploy?template=https://github.com/chiefonboarding/ChiefOnboarding. Heroku will then ask you for some details. Please be careful to put them in correctly, otherwise your app will not start."]},{"l":"Update Heroku","p":["Please make a backup of your database before doing this.","Install the Heroku CLI and authenticate yourself.","Download the ChiefOnboarding git repo: git clone https://github.com/chiefonboarding/ChiefOnboarding.git","Add your heroku git url as a git remote. You can find this url on the app's settings page -> app info -> Heroku git URL. git remote add heroku_repo repo_url(replace repo_url with your own url).","Then push it up: git push heroku_repo master"]},{"l":"Next steps","p":["As of right now, your ChiefOnboarding instance will be up and running. Though, it might not be fully functional yet. There might be some components that you want to add, like email, object storage (saving files), text messages or the Slack bot."]},{"i":"object-storage-updownloading-files","l":"Object storage (up/downloading files)","p":["Add this CORS configuration there (change YOURDOMAIN):","Add your newly created policy to the user and click on 'Next'.","Caddyfile","Click on 'Add user'.","Click on 'Add'.","Click on 'Next' again. Twice.","Click on 'Review policy'.","Click on your newly created bucket.","Example variables:","For 'Actions' pick 'GetObject', 'DeleteObject' and 'PutObject'.","For 'Service' pick 'S3'.","Give it a fancy name and click on 'Create policy'.","Give it a fancy name and click on 'Next'.","Give it a fancy user name and select 'Programmatic access', so we get the keys we need to enter in ChiefOnboarding. Click on 'Next'.","Go back to the set up screen of your IAM user and click on the refresh button to refresh policies.","Go to 'Attach existing policies directly' and click then 'Create policy'.","Go to https://console.aws.amazon.com/iam/home#/users.","Go to https://s3.console.aws.amazon.com/s3/home and click on 'Create bucket'.","Here is a step-by-step for AWS:","If you want to use Minio (self-hosted), then you could use something like this as an example for both ChiefOnboarding and Minio:","In the bucket, go to 'Permissions' and then to 'CORS'.","Keep everything at the default (or change it to your liking) and click on 'Next'.","Keep everything at the default and click on 'Next'.","Note that you might still need to set some of the environment variables below (such as the bucket).","The bucket is now created. Up next, we need to create a user to be able to post and get from this bucket.","The instructions below will set everything up by using client/secret token. You can also use a profile/role if you prefer. Under the hood, ChiefOnboarding uses boto3, which means that it will search for credentials by itself as well. Please see the documentation for those boto3 environment variables here: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html","Under 'Resources', enter the correct bucket name and for the 'Object name' select 'Any'.","You can use AWS S3 for this, but you are also free to use any other provider who provides the same API. For example: Wasabi, Vultr, Digital Ocean, or Fuga cloud.","You will now get to see the Access key ID and the Secret access key. Add those to your environment variables or .env file."]},{"l":"Email","p":["If you want to send emails to anyone, then you will need to add a provider. Technically, if you are using a VPS, you could start selfhosting your own SMTP server, however we recommend against that. In any case, you need to set up the email environment variables if you want to start sending any emails.","ChiefOnboarding is using the django-anymail package to support a wide variety of email providers(Sparkpost is not supported in ChiefOnboarding).","If you want to enable emails (this is highly recommended), then you will first have to set the from email and choose one of the providers below or go with SMTP and use pretty much any provider.","Example for the email header variable:","Email providers:","Postmark:","Mailgun","Mailjet:","Mandrill:","SendGrid:","Sendinblue:","SMTP:","For SMTP, you only need to set either EMAIL_USE_TLS OR EMAIL_USE_SSL to True. If you set both, then it will likely not send out any emails."]},{"l":"Custom email template","p":["You can set your own email template if you want. You can see the default one here: https://github.com/chiefonboarding/ChiefOnboarding/blob/master/back/users/templates/email/base.html","Some things are rendered dynamically. You can use this as an example:","Don't change whatever is within the brackets. Feel free to customize everything around it however you would like!"]},{"l":"Ratelimits of failed login attempts","p":["By default, ChiefOnboarding uses allows users to attempt 10 times before the user gets blocked by IP. You can change the defaults:","AXES_ENABLED: Default: True. Set to False if you want to disable blocking users from trying again (not recommended).","AXES_FAILURE_LIMIT: Default: 10. Sets the amount of attempts before user gets blocked.","AXES_COOLOFF_TIME: Default: 24(in hours). After 24 hours the IP address gets cleared again.","AXES_USE_FORWARDED_FOR: Default: True. In many cases ChiefOnboarding is deployed behind a proxy (i.e. Docker or Heroku reverse proxy). This allows you to get the IP address from the refer header. Without this, it would log internal ip addresses, which means that users will share the same ip address and get locked out unintentionally."]},{"l":"Text messages","p":["If you want to start sending text messages to new hires or colleagues, then you will need to signup with Twilio and get a number there.","Sign up at Twilio if you haven't yet.","Go to https://www.twilio.com/console/phone-numbers and click on the red 'plus' icon.","Pick a number you like and purchase it. Make sure it allows text messages.","Go to https://www.twilio.com/console/project/settings","You can take the account_sid and api key from there and add those to your environment variables or .env file.","Example variables:"]},{"l":"Error logging","p":["This is entirely optional, but if you want to catch errors comming from your instance, then Sentry is ready to be used for that. No system is ever bug-free. Errors happen. This is really useful if something happens with your instance and you want to give us a detailed log about it. You can share the error log and we can then fix it much quicker. Obviously, we are not connected to your Sentry account, so you will have to let us know about it!","You will have to provide a URL to send the requests to. This URL may be from the hosted version of Sentry or the on-premise one. Both will work just fine.","Go to sentry.io","Sign up and then create a new 'Project'.","Select 'Django' and give it a name.","Copy the value of the DSN url. Example: https://xxxxxx.ingest.sentry.io/xxxxxx.","Example variable:"]},{"l":"Google SSO","p":["This will allow you to use the 'Log in with Google' button on the log in page.","Go to https://console.developers.google.com/apis/consent and make sure you are logged in as the admin of the Google organization.","Create a new 'Project' and give it a fancy name. Once it's created make sure you are in that project (you can see that in the top bar).","You will be asked for what type of app you want to register. Choose 'Intern', only people from your organization should log in to your app. Click on 'Create'.","Fill in the details accordingly. You don't have to change the scopes, those are fine. Under 'Authorized domains', fill in your own site url and the url of the ChiefOnboarding instance.","Click on 'Create'. You will be taken back to the page you previously landed on.","We just set up our authentication screen for people that want to sign in. Up next, we need to create credentials that we can put into the ChiefOnboarding instance, so we can actually show that authentication dialog.","Go to https://console.developers.google.com/apis/credentials","Click on 'Create credentials' at the top of the page and choose Client-ID OAuth.","You will be asked for the type of app. Pick 'Web application'.","Under \"Authorized JavaScript-sources\" enter the domain name of where ChiefOnboarding is running on.","Under \"Authorized redirect-URLs\" enter this: https://YOURDOMAIN/api/auth/google_login.","Click on 'Create' and you will get the Client-ID and Client-secret that you need to fill in on your ChiefOnboarding instance.","Submit the form on ChiefOnboarding and enable the Google login integration in settings->global and you should be good to go.","You will only be able to let people log in who already have an account in ChiefOnboarding."]},{"l":"Slack bot","p":["This is the bot that will ping your new hires and colleagues with things they have to do. This is needed if you want to use ChiefOnboarding in Slack. Since there is no centralized app, you will have to create an app in Slack yourself. The benefit of this is that you can use your own profile picture and name for the bot.","Manifest (webhook) - replace XXX with your domain name:","Go to https://api.slack.com/apps and click on 'Create New App' (big green button, can't be missed). Click on \"From an app manifest\".","Select the workspace where you want to install ChiefOnboarding.","Copy and paste the manifest in the little text box.","Review the permissions and then click on 'Create'.","Scroll a bit on the new page and notice the App credentials part. You need the information there to fill in on the settings/integrations page in your ChiefOnboarding instance.","Fill in the details accordingly.","Submit the form. You will now get a \"Add to your Slack team\" button. Click it and verify that you want to install your bot in your Slack team.","Go back to your Slack bot and go to \"App Home\". Then scroll down till you see: \"Show Tabs\". Enable the \"message tab\" and check the \"Allow users to send Slash commands and messages from the messages tab\".","That's it!"]},{"i":"oidc-single-sign-on-sso","l":"OIDC Single Sign-On (SSO)","p":["To enable OIDC, you must enable \"Allow users to login with OIDC\" in the admin settings page at https://example.com/admin/settings/general/.","You may need the redirect URL for your Identity Provider (IdP). The REDIRECT_URL should be set to https://example.com/api/auth/oidc_login.","If you set OIDC_FORCE_AUTHN=True, the login page will automatically redirect to the OIDC IdP."]},{"l":"Role Mapping","p":["In this example, we use CAS as the IdP and modify the zoneinfo field to display group information. You can see OIDC_ROLE_PATH_IN_RETURN='zoneinfo' is set accordingly.","If your groups (roles) are stored deeper in the JSON structure, like:","You can set OIDC_ROLE_PATH_IN_RETURN='B.roles' using dots.","There are three patterns to map ChiefOnboarding's role with OIDC_ROLE:","For Admin, apply OIDC_ROLE_ADMIN_PATTERN to OIDC_ROLE","For Manager, apply OIDC_ROLE_MANAGER_PATTERN to OIDC_ROLE","For Newhire, apply OIDC_ROLE_NEW_HIRE_PATTERN to OIDC_ROLE","OIDC_ROLE_DEFAULT is used to set other users' roles; you likely don't need to change it. If you don't want to use role mapping, simply leave it as a space.","If you do not want the OIDC provider to update roles, then you can disable it by setting OIDC_ROLE_UPDATING to False."]},{"l":"Logout","p":["Since this is an SSO implementation, we recommend setting OIDC_LOGOUT_URL. When you log out, it will redirect to the OIDC_LOGOUT_URL.","Here's the updated configuration example:"]}],[{"l":"Development","p":["If you want to contribute or just play around with the source code, the first step would be to download the source code. Then run this to get it all up and running:","Please note that it could take a few seconds everything is set up. Ignore any error messages you see, this is generally because the database hasn't been migrated yet. It will do that at the end automatically.","Once it's ready, go to http://0.0.0.0:8000 and you should see the setup screen. Fill in the details and you will get a bunch of dummy data as well!"]},{"l":"Enable better logging","p":["If you want to start developing/debugging and need more verbose log messages, then you can enable debug log messages with this environment setting:"]},{"l":"Adding a new language","p":["If you want to add a new language, then you will have to follow these steps:","Replace lang with the shortname of your language (e.g. nl, en, or es) in the command below","It will generate a new file for you to fill in. It's a .po that you can edit (with a text editor or through one of the many tools).","Up next, you will need to add the language to the list of languages. Go to back/back/settings.py and add your language to this array https://github.com/chiefonboarding/ChiefOnboarding/blob/v2.0/back/back/settings.py#L371. That way, it will show up in the lists to choose the language."]},{"l":"Updating existing translations","p":["Simply run this command and it will update all current translations:"]}],[{"l":"Architecture","p":["ChiefOnboarding is build on top of Django (Python). It's mostly a \"boring\" app in the case that we don't use any type of frontend framework to decouple the frontend from the backend. It does use some sprinkles of JavaScript to create some moving elements. There is some HTMX, VueJS, jQuery, Bootstrap JS and a few other scripts.","A few things you should know about ChiefOnboarding:","It uses Pytest for testing the code. For object creation, it uses factoryboy. You will find factories.py in almost every app.","It relies heavily on background tasks. You can find those tasks in the tasks.py files in the apps folders. Especially the Slack bot and the Sequence s use those a lot.","Supervisord is set up for docker-compose. It will run two processes: the background worker ( Django-Q) and python manage.py runserver for the server.","Sequences are basically blueprints for new hires. The Condition s that are in there are all connected to the Sequence. Once a sequence gets assigned to a new hire, it will duplicate the Condition and assign it directly to the User model. This means that if an admin would change a Condition in a Sequence, then that won't affect new hires that are currently going through sequences. There is one caveat with that though: if a template gets changes (i.e. a to do item or resource), then that will reflect for all people that don't have a custom one. Once you make changes to a template in a sequence, then it becomes a custom item and those items will not update when you update the original one.","Here is an overview of the database models of ChiefOnboarding:","ChiefOnboarding models"]},{"l":"Folder structure","p":["In the root of the repo, there are a bunch of files and folder. The files are mostly there for deployment and development. The bin folder is purely for Heroku to generate the messages necessary for enabling multilanguage.The .github/workflows folder probably speaks for itself, that's for running workflows (tests, deploy to Docker, etc). The docs folder represents all the docs that are shown at https://docs.chiefonboarding.com. The back folder is where the actual application lives."]},{"i":"backadmin","l":"back/admin","p":["In this folder you will find only things that are mainly used by admins. These are all templates ( to_do, resources, introductions, appointments, badges, preboarding), people options ( back/admin/people/views.py and back/admin/people/new_hire_views.py for new hires), admin_tasks(things colleagues need to d for new hires), sequences, and settings(global as well as personal)."]},{"i":"backback","l":"back/back","p":["This is just the core app that Django creates by default. You will find the settings.py file in there and the base urls.py file."]},{"i":"backfixtures","l":"back/fixtures","p":["These are the default fixtures that are used for a limited part of testing and mostly for loading dummy and default data once someone installs ChiefOnboarding. This happens for both local developing and in production."]},{"i":"backlocale","l":"back/locale","p":["This is were all translations are stored."]},{"i":"backmisc","l":"back/misc","p":["This folder is pretty much used for everything that doesn't fit anywhere else. For example, uploading to object storage is used throughout the platform and isn't attached to anything specific."]},{"i":"backnew_hire","l":"back/new_hire","p":["This covers the new hire portal."]},{"i":"backorganization","l":"back/organization","p":["When someone installs ChiefOnboarding, it will create one Organization by default. You can see this as the settings model for the site. Everything that is configurable by the admins (i.e. color scheme, default email template and slack settings are all stored in the Organization. You can call the object for this everywhere, using org."]},{"i":"backslack_bot","l":"back/slack_bot","p":["This is used only for the Slack bot. For local development, there is an option to enable websocket support, though it can be a bit flaky."]},{"i":"backstatic","l":"back/static","p":["This is where all static files are stored. Things like CSS, JavaScript and images."]},{"i":"backuser_auth","l":"back/user_auth","p":["This is for authenticating the user. Be it through SSO or plain username/password. ChiefOnboarding mostly relies on the Django authentication module (and therefore uses sessions). django-axes is also installed to prevent brute-force attacks."]},{"i":"backusers","l":"back/users","p":["This is where the User model can be found. It has been put in a separate folder as the User model contains all sorts of user accounts (i.e. new hire, admin, manager). Those are differenciated through an option field on the model."]}],[{"i":"integrations--webhooks-beta","l":"Integrations / Webhooks (Beta)","p":["ChiefOnboarding allows you to create integrations or trigger webhooks that can be triggered either manually or through a sequence. You can view some examples at https://integrations.chiefonboarding.com. You are free to copy them. If you created a cool new integrations, then please post it there. That way we can help eachother out by not re-inventing the wheel! Thanks a lot!","There are two types of integrations:","An integration to trigger a URL on an third party service","An \"sync users\" integration, which allows you to import users from a third party to ChiefOnboarding (manually or through a background cron job) or update specific information to the user (for example, save an external ID per user)"]},{"l":"Integration to trigger a third party url","p":["Here is an example of a manifest of an integration (in this case to add a user to an Asana team):","Let's go over the items:"]},{"l":"Form","p":["This is the form that is shown to you when you add this to a sequence. The form should consist of items that you would like to have different for different type of people. In the example above, the form allows you to pick a specific team to add the user to. For example: you probably don't want to add a developer to the HR team in Asana. So, the team is what you can customize every time you add the integration to a user or in a sequence.","You can customize where we get the info from and what an admin should fill in. The form should always be an array and allows the following properties:","id: This value can be used in the other calls. Please do not use spaces or weird characters. A single word is prefered.","name: The form label shown to the admin.","type: options: choice, multiple_choice and input. If you choose choice, you will be able to set the options yourself OR fetch from an external url.","For choice:","url: (if you have static items, then use items instead). The url it should fetch the options from.","method: Default: POST. You can use any request method you would like.","headers: (optionally) This will overwrite the default headers.","data_from: The property it should use from the response of the url. In some cases, it might happen that what you get more than just the options you need. For example, you get a dictionary instead of an array and need to go a little deeper in the data. For example: you get a dictionary that has the prop options which has an array with the items. You can then specify options as the value for data_from and it will use that. If you need to go deeper, you can use the dot notation to do that. E.g. data.options.items. Leave this field blank if you are using predefined items.","choice_value: The value it should take for using in other parts of the integration (for example the id property of the items you get from the server). Default: id.","choice_name: The name that should be displayed to the admin as an option. Default: name.","items: (if you are not fetching items from a url) You can add an array here with objects in them with the props: id and name. For example: [{id: 233, name: option 1}, {id: 234, name: option 2}]."]},{"l":"Exists","p":["Exists is an option to check if a user is already part of a team. If you add this property to your manifest then it will show up under new hire -> access. From there, you will be able to manually enable/disable an account for them. Generally, you should skip this option if you are making any calls not related to account provisioning.","url: The url to check if the user exists. Everything that comes back is parsed to a string and then checked against.","method: The method for lookup that is being used. E.g. POST or GET.","expected: Whatever we expect. Generally this will probably be a positive message or the new hire's email. You can use new hire values by wrapping them around double curly brackets.","headers: (optionally) This will overwrite the default headers.","fail_when_4xx_response_code: Default: True. If the server response with a 4xx status code, then that's considered a failing request. In some cases, apis will return a 404 if the user does not exist. In that case, set this to False, so it can check for the expected value."]},{"l":"Revoke","p":["Revoke is an option to revoke access of a user to a third party. If you add this property to your manifest then you will be able to revoke access through the dashboard. Generally, you should skip this option if you are making any calls not related to account provisioning.","This uses the same setup as the execute part below (but is limited to url, data, method and headers). It expects an array with requests in it."]},{"l":"Execute","p":["These requests will be ran when this integration gets triggered.","url: The url where the request will be made to.","data: This is the data that will be send with it.","method: The request method. E.g. POST or GET.","headers: (optional) This will overwrite the default headers.","store_data: (optional) This can be used to store data to the new hire. Let's say you create a document through an API and you need to store the document ID that is relevant to the new hire, then you can do that with this. You can put a dictionary here with a key and value of the new hire prop name and the notation of where to get the data. You can use a dot notation to go deeper in the json. This data is only available in items assigned to this new hire and can be used anywhere (in both content items (todo, resources etc) and integrations that get triggered later).","Example:","continue_if: (optional) This can be used as a blocked. If you want to block an integration if a response is not what you expect, then you can do that with this. If you need to wait for a response to come back (waiting for a background task for example), then you can use polling and continue with the call with the response changes. It will check every response and stop polling when it matches.","With this config, it will check the response for the status property in the detail property (so for example: {detail: {status: done}}). It will check for the value done, which would be valid in this case and therefore continue with the integration.","polling: (optional) You can use this to poll a url if you are waiting for a background (async) task to be completed. It will retry fetching the url for as many times as you specify at the interval you want. Here is an example config:","This config will try to fetch the same url for 60 times and wait 5 seconds between each call (so max 300 seconds) and will keep going until the status of the response is done. If it exceeds the 300 seconds, then the integration will fail.","save_as_file: (optional) If you expect a file as a response from the server, then you can define this with the filename you want it to have. For example: save_as_file: filename.png. You can then use this filename in the files parameter for any requests that you make after this one.","files: (optional) You can use this to define what you want to send to the api as files. Note that you will have to download the files in the same integration before you are able to use this. This item needs to be defined like this:","It will search the previous responses by the key of the files dictionary. In this case that would be filename.png, so you would need to have save_as_file: filename.png in any of the previous requests."]},{"l":"Headers","p":["These headers will be send with every request. These could include some sort of token variable for authentication."]},{"l":"Oauth","p":["If you need to use OAuth2 to get a token, then you will need to use this. Just create a prop called oauth and then in that use these properties:","authenticate_url: This is the url that is used to send the user to the login/authorize the connection (this should be a url to the third party). This is always a GET request. It expects an url here.","access_token: This is used when you come back to our site with a token. With that token, it will need to fetch an access token from the third party (and perhaps a refresh token). Format is an object like the execute part.","refresh: Used to refresh the token to get a new one, if this is not added, then it will assume that the token is permanent. Format is an object like the execute part.","without_code: Default: False. Enable this is a valid callback won't return a code query in the url. In some cases, we don't get it and also not need it."]},{"l":"Initial data form","p":["This is a form that you can create to fill in when you add this integration to your instance. Any sensitive info should be filled in here, instead of in the manifest itself. Data that gets filled in here will be saved encrypted in the database. The manifest itself does not get encrypted. So, again, any tokens, authentication, sensitive info should be filled in through this form and not hardcoded!","You can obviously add as many as you want. You can use these variables by using the id in any of the other parts of the manifest.","id: Reference for any other part of the manifest. Wrap it around double curly brackets to use it.","name: The label of the field. Please do not use spaces or weird characters. A single word is prefered. Use generate to generate a secret value, use this for i.e. one-time password.","description: Any other info you want to leave to make it clear where to find this value. Mainly used for documentation and/or sharing."]},{"l":"Post execute notification","p":["Defined as post_execute_notification. Gives you the ability to send a text message or email to someone after this integration has been completed.","type: Either email, or text. Depends if you want to send an email or text message.","to: Use a fixed email or (preferably) a placeholder.","subject: In case of an email, define the subject header.","message: The message that should be send (plain text)."]},{"l":"Variables","p":["Throughout the manifest you can use the variables that you have defined in the initial_data_form or the form wrapped around in double curly brackets. On top of that, you can also use new hire values. You can use:","email: New hire's email address","manager: The manager's full name","manager_email: The manager's email address","buddy: The buddy's full name","buddy_email: The buddy's email address","position: New hire's position","department: New hire's department","first_name: New hire's first name","last_name: New hire's last name","start: New hire's start date","Please do not overwrite these with your own ids","You can also use data from previous requests. If you have an integration with 3 requests, you can use the data from the request 1 in request 2 and the data from request 1 and 2 in request 3. You can do that by using: {{ responses.index.the_data_you_need }}(index starts at 0). So for example, you get this response from the first request:","You can then use {{ responses.0.form_id }} in any of the following requests in the same integration."]},{"l":"Notes","p":["If triggering an integration fails, then it will retry the entire integration again one hour after failing. If it fails again, it will not retry.","If you are using any of the integrations from the repo at: https://integrations.chiefonboarding.com then you have to validate them yourself. This is a user repository and we do not actively moderate the submissions there. Please always validate the urls where requests are going to make sure it's legit."]},{"l":"Sync users integration"},{"l":"Creating users","p":["You can create custom import integrations to pull users from a third party and put them in ChiefOnboarding. This is fairly universal and will work with most APIs. A sample integration config will look like this:","The setup is very similar to what we have for other integrations to trigger a webhook. The most notable differences are:","data_from: this is to indicate where the users are located in the response. You can use a dot notation if need to go deep into the json to get the data.","We then also need to define where the data is stored in the users array (for each object). We can do that with data_structure. In there, you can define the values you want to copy. Please note that only email, first_name and last_name can be used for now.","So for the current config, we expect a JSON response from the third party like this:","Other values in the JSON will be ignored.","You can run this integration manually (by going to people -> colleagues -> import... \". If you provide a \"schedule\" prop (cron notation), then it will run this in the background. It will create the users automatically (default role is \"other\")."]},{"l":"Updating users","p":["This will allow you to save additional data from a third party to your user. This can be helpful in case you need a specific ID in an integration that is tied to this user for example. You cannot update core attributes of a user (such as their email or first name). You can only save extra information to the user, which can then be used in integrations or content boxes.","An example integration to save the bambooHR user id to the user in ChiefOnboarding:","The schedule prop is mandatory here as it would otherwise never run, you cannot trigger this manually. The other main difference with the import option is the \"action\". It's \"update\" in this case. You will also have to provide the email key in the data_structure, so ChiefOnboarding knows how to match the user. If no user can be found with the provided email, then it will get skipped."]},{"l":"Paginated response","p":["Sometimes, we might not get all items at once. We have something to cover that too. This only works for syncing users and importing users.","amount_pages_to_fetch: Default: 5. Maximum amount of page to fetch. It will stop earlier if there are no users found anymore. There is a limit to this number. Please see the note below.","There are two ways of fetching a new page:","Sometimes an API will only return a token and we will have to build the url ourselves. (Google does this for example)","In most cases, you will get a full url that you can use to fetch the new page of users.","For case 1, you will need to provide two items (the url and where the token is):","next_page_token_from: the place to look for the next page token. You can use the dot notation to do go deeper into the JSON. If it's not found, it will stop. next_page: This should be a fixed url that you should put here. You can use {{ NEXT_PAGE_TOKEN }} as the variable to include the previously found next_page_token_from value.","For example, this is necessary for Google:","For case 2, you will only need to provide the place where we need to look for the URL with this item:","next_page_from: the place to look for the next page url. You can use the dot notation to do go deeper into the JSON. If it's not found, it will stop.","Note: fetching users is being done live when you visit the page. If you set a high amount of pages to be fetched, then this might cause a timeout on the server. It makes rendering all users on the client also very sluggish. We recommend to not load more than 5000 users or not more than 10 pages (if a timeout of 30 seconds is set on your server (like Heroku for example)), whichever comes first. If you do need more, then we recommend going for an alternative method of importing users."]}],[{"l":"API","p":["This API will allow you to programmatically create new hires. The API does not work when you are logged in with sessions (logging in through the log in form), you will need to use a token to get access. These tokens do not expire and you can create them through shell."]},{"l":"Setup","p":["Enable the API through the environment variable:","Just to be safe, run the migrations for the token table docker-compose run --rm web python3 manage.py migrate(docker) or redeploy on Render/Heroku. Up next, you will have to generate a token to authenticate with the API. You will have to attach a user to it, like this:","Use the email address from an admin user there. You will then get to see the newly created token. Now you can make calls to the API. Please note that if you ever remove this person, then the token will also be revoked.","Example:"]},{"l":"API usage example"},{"l":"Adding a new hire","p":["We would like to assign a buddy to this new hire, so first we need to get a list of employees to find the id of our buddy. Getting all employees that are in ChiefOnboarding:","We might also want to add some sequences to the new hire. In that case, we need the ids of the sequences we want to add. We can get all sequences with this request:","Create the new hire:","first_name, last_name, role and email are required","Role options (note: keep an eye on updates, this will likely change soon):","0: new hire","1: administrator","2: manager","3: other (user will not get notified and does not have any meaningful permissions, no slack connection either)","The data part of that query (with explanation):","It will return the full new hire object including the ID of the new hire."]}],[{"l":"Changelog"},{"i":"v200","l":"v2.0.0","p":["API has breaking changes. Please see the dedicated API page for that.","Assign admin tasks in sequence to admin/manager instead of a specific person","BREAKING CHANGES:","Buttons posted in Slack before this migrations might become invalid.","Change admin to manager and vise versa","Change channel where bot sends messages to","Change email template","Completely new look","Docs have been updated and moved to the ChiefOnboardig repo (instead of a standalone repo)","Google account creation will be temporarily removed. Record will still be in the database and will be available for use when we create this integration again. You could also remove this integration before migrating if you want to.","Moved from SPA back to MPA (dropped almost all javascript requirements)","Notifications on both the new hire and admin side on various actions","Scheduled access items that have been scheduled on the old version will not be executed anymore - table is dropped and functionality has been replaced","Selectboxes have been dropped temporarily from forms. Those will be gone after migration.","Sequence timed based triggers can now be triggered at a custom time (used to be always at 8 am)","Slack account creation will temporarily be removed. You can add it back when you go to our integrations site (see above). If you need the old key, then you can find it in Slack under your apps list (api.slack.com).","SLACK BOT: Under \"Interactivity & Shortcuts\" in the config of your bot ( https://api.slack.com/apps), change \"callback\" to \"bot\" in the URL. It should now be the same URL as you have under \"Event Subscriptions\". You will also need to change the redirect url. Change \"api\" to \"admin\" in the url and save it.","Slack doesn't need to depend on webhooks anymore - websocket is now supported as well (so you can also use it without having a public access point).","Some urls will not be accessible (like preboarding links). I am not setting up a redirect for this. These will return 404.","Support for custom integrations and webhooks created by you ( https://integrations.chiefonboarding.com/ https://github.com/chiefonboarding/ChiefOnboarding/blob/v2.0/docs/Integrations.md)!","You can update Slack to use the internal websocket instead of the HTTPS calls webhooks. That way, you remove one open endpoint (technically, you could use the app now with Slack behind a VPN). Webhooks is the default as we have noticated that they are more stable."]},{"i":"v1223","l":"v1.2.23","p":["Fix email default from field for password reset","Fix not being able to remove external messages (slack/email/text)"]},{"i":"v1222","l":"v1.2.22","p":["Fix related to v.1.2.20"]},{"i":"v1221","l":"v1.2.21","p":["Bump Django version"]},{"i":"v1220","l":"v1.2.20","p":["Fix bug with sending custom email (replacing variables)"]},{"i":"v1219","l":"v1.2.19","p":["Fix render database not in same region as app"]},{"i":"v1218","l":"v1.2.18","p":["Remove DO as DO won't work with Django Q (no support for multiprocessors). For reference: https://www.digitalocean.com/community/questions/app-platform-multiprocessing-python?answer=69003","Fixed Render to work with supervisor setup (no need to create an extra worker).","Fixed Docker hub link."]},{"i":"v1217","l":"v1.2.17","p":["Forcing Python 3.7 to avoid SemLock error on DO/Render"]},{"i":"v1216","l":"v1.2.16","p":["Django version update","Fix resources in Slack"]},{"i":"v1215","l":"v1.2.15","p":["Limit auth with url only to new hires","Fix missing import","Fix Slack authentication bug"]},{"i":"v1214","l":"v1.2.14","p":["Remove google delete user"]},{"i":"v1213","l":"v1.2.13","p":["Add deploy to DigitalOcean button","Add deploy to Render button"]},{"i":"v1212","l":"v1.2.12","p":["healthcheck url + allowed hosts fix","Update docker image number"]},{"i":"v1211","l":"v1.2.11","p":["additional update regarding v1.2.10"]},{"i":"v1210","l":"v1.2.10","p":["Update slack add bot redirect button - remove legacy bot permissions"]},{"i":"v129","l":"v1.2.9","p":["Fix bug with adding introduction/appointment items"]},{"i":"v128","l":"v1.2.8","p":["Remove old signals file (old setup)","Fix not being able to add to do items through 'add sequence' button","Fix showing empty 'to do' conditions on new hire timeline"]},{"i":"v127","l":"v1.2.7","p":["Adding default username/password to dev docker-compose file","Adding migrate cache table to dev docker-compose file","Adding node_modules to gitignore","Updates for Django Q. Stop having it redo every failing task indefinitely."]},{"i":"v126","l":"v1.2.6","p":["Show error message when trying to send Slack test message without Slack account attached","Fix showing preboarding preview part in a sequence","Fix Slack syncing issue","Update Django dep to newest version","Update Docker version number (routine task)","Fix showing old data in sequences (when adding a new one)"]},{"i":"v125","l":"v1.2.5","p":["Fix docker copy command"]},{"i":"v124","l":"v1.2.4","p":["Simplify docker setup (remove folders that are not necessary in container)"]},{"i":"v123","l":"v1.2.3","p":["Putting new hire start date further in the future (fixtures)","Fix for blocking collectstatic on restart of container","Enforcing email address of admin account to be lowercase. The email address would always be registered as lowercase and could therefore output incorrect info (on first run - creating admin account).","Updated Docker version"]},{"i":"v122","l":"v1.2.2","p":["Another docker build fix"]},{"i":"v121","l":"v1.2.1","p":["A docker build fix"]},{"i":"v120","l":"v1.2.0","p":["TOTP 2FA support. You can now use andOTP, Aegis authenticator, Google authenticator, Authy or any other OTP app that you use to set up 2FA (with QR code).","New editor and video support TipTap. We now support native video upload to S3. It will show up as a video in the portal and as a normal link in Slack.","SMTP support","Refactor Docker setup. Swapping Celery with Django Q. All running with supervisor now. Redis is now deprecated."]},{"i":"v110","l":"v1.1.0","p":["Docker image","Heroku deployment"]},{"i":"v100","l":"v1.0.0","p":["Automatically add new hires when they join Slack (optionally)","Subject to custom email message. Used to be \"Here is a quick update\"","Default sequences. Sequences that are always added to new hires by default."]}]]
\ No newline at end of file
+[[{"i":"whats-chiefonboarding","l":"What's ChiefOnboarding?","p":["In one sentence, ChiefOnboarding is an open-source remote-first employee onboarding platform that helps you streamline the employee experience for both the new hire and you through Slack or the web portal.","With ChiefOnboarding you can create generic new hire timelines and apply them to specific new hires. Timelines are designed in a way that it will reduce the overwhelming feeling that a new hire often gets on their first few days and increases overall quality due to consistency.","Let's start at the beginning. Your new hire just said: \"Yeah! I want to work for you\" and you both signed the contracts. Up next, you need to make sure that your new hire knows things like the dress code, when they should start and what to expect from their first few days. That's often called pre-boarding.","With our pre-boarding module, you can create several pages with information, pictures, files, lists and so on with everything that your new hire needs to know. You can even add custom forms that will allow you to get some information from your new hire before they start. How about asking them for their favorite snack and adding that to their goodie pack to surprise them?","Oh... but someone needs to make that goodie pack, right? That's why we created our \"tasks\" module. In the timeline you can add tasks for your colleagues. Those are automatically created and colleagues will be notified of them. Colleagues are able to leave comments and check them off. They can even collaborate with others on a shared task.","In the meantime, our Slack bot will send your team a message letting them know that someone is starting very soon. Your colleagues will be able to leave a custom welcome message, which will show up in the new hire's preboarding pages. Talking about keeping it personal!","It's a few days before the new hire starts. It's probably a good idea to give the buddy and manager a quick heads-up about the new hire starting soon - better be safe than sorry. Add a custom Slack/Email/Text message in the timeline so they will be reminded on time.","Oh no, you still need to set up their user accounts (Slack, Google, Asana etc) to give them access to the things they will need. Your IT department is already clocking in overtime... Our account provisioning module will take care of that for you! Add the integrations to your timeline on the day you want and let the platform create the accounts for them.","It's the new hire's first day and your new hire gets to meet a lot of people in your Slack team. To avoid any awkward conversations, your new hire can look into the colleagues directory to see who does what. Even better yet, you can send colleague introductions directly to your new hire. This is great for introducing their direct coworkers.","There are some tasks that every new hire needs to complete, right? You can easily create those todo items and follow up on those or remind them if they are late on one (this can also be automated by the way). Got a quick assessment for them to complete? Throw it in a to do item and have them complete it!","Adding too many to do items could be a bit demotivating. Especially if they are mostly boring things that just need to get done. You can obviously spread them over the first few days/weeks, but that might not be enough. We hear you... How about rewarding them with a badge? Throw a condition in the timeline that waits for a few to do items to be completed and then sends them a custom message with a reward. As easy as that.","Over the next few weeks, they will have to learn a lot of things. General things like how to request a holiday or how to collect their paycheck come to mind. With our \"Resources\" module, you can easily create small wiki's with all the information they need. You can let them go through the resource by themselves, or convert it to a course to validate that they actually read through it all with questionaires.","Those timelines are extremely flexible. We understand that every company is different and that you need a custom approach to your onboarding plan."]},{"l":"Privacy","p":["We care about your privacy. ChiefOnboarding does not contain any weird or creepy trackers and you can even host it on your own servers if you really want full control over it. You might find that some of the integrations require quite a lot of permissions from a third party. That kind of info is stored in encrypted fields and I want to emphasise that ChiefOnboarding does not ping home, ever! We will never receive any information from your server.","We can collect error logs for users who use our servers. This will ensure quick bug fixes and therefore improve stability of the platform. This is always on an opt-in basis - it's disabled by default and we ask for permission."]},{"l":"Support","p":["Over the past 1,5 years (Sept 2020 - August 2022), we have had an average response time to questions of 1 hour and an average response time of 2 hours for bug fixes (actually fixing the bug, not just acknowledging the bug report). While those aren't official SLAs, we do our best to keep those averages as low as they are. Email support is only part of our paid plans, users hosting their own copy will have to fallback to Github issues (and it takes more time to get back to you - paying customers are always in the priority queue). With the support and managed package, you get the best of both worlds: the transparancy of open source software with the fast support of a premium software package.","Helpful links:","ChiefOnboarding repo: https://github.com/chiefonboarding/ChiefOnboarding","Pricing: https://chiefonboarding.com/pricing"]}],[{"i":"how-to--demo","l":"How to / Demo","p":["At ChiefOnboarding, we currently don't do demos with potential customers. Demos take a lot of time and are quite similar between potential customers. You all come with the same goal, right? Improving your onboarding process.","Underneath, you will basically find the transcript of a demo. You will get to see most of the features that our software provides and you can easily come back to it, if you want to look something up again. At the same time, we can keep working on features that you want.","As always: if you have a question, feel free to send us an email- we are fast at replying (often within an hour)."]},{"l":"Sequences","p":["At ChiefOnboarding, we base everything around sequences. Sequences are basically timelines which will map out the new hire's onboarding path. It looks like this:","Let's break it down a bit:","Sequences consist of blocks. We currently have 3 types of blocks:","General blocks","Block before the new hire starts","Block after the new hire has started","Block based on the completion of a to do item","Unconditioned block"]},{"l":"The general blocks","p":["There are three types of general blocks that you can choose from. You can create a block that triggers before the new hire starts. You could use this to create tasks (we will get to this later) for colleagues for things they need to do or send some emails/slack/text messages.","The second type of general blocks are the ones that start after the new hire starts. These are marked in workdays, so it doesn't really matter if your new hire starts on a Monday or Thursday - ChiefOnboarding will skip the weekends and not bother the new hire on those days. Example: Monday is workday 1, next week Monday is then day 6. You can add a bunch more in these types of blocks (which we will get into in a bit). We will notify the new hire of any newly added things - you can disable this if you don't want that.","All of the above blocks trigger at 8 AM in the new hire's timezone. Yes, ChiefOnboarding is totally remote friendly, we support multiple time zones and multiple languages.","The third type of general block is a special one. You can have things happen based on a to do item. We will get into to do items in a bit, but basically what this means is that you can wait for your new hire to complete a to do item and then it will trigger to create a new to do item for the new hire or perhaps send a message to a colleague. The possibilities are endless."]},{"l":"The unconditioned block","p":["You can only add one of these and you can add things in here that are automatically added to the new hire when you add the sequence to your new hire. You could add some random stuff in here that your new hire might need or that they need right from the start. Think of some policies and some default to do items.","Also often used to add preboarding pages that your new hire will be able to see BEFORE they join the company. A pre-boarding page basically looks like this:","preboarding edit","And you can preview it with the preview button, it will look like this:","preboarding view","You might have noticed the little part at the bottom that says \"Form options\". You can actually build a custom form where you can allow your new hire to send some information back to you. Perhaps you want to know what their favorite snack is."]},{"l":"Templates","p":["So what could we put in these blocks? We have created a few different types of templates that you could add in these. You could create those templates before you start to create the sequence, but you can also just add items as you go."]},{"l":"To do items","p":["To do items look like this (for you):","todo edit","Let's break it down a bit more.","I think the title speaks for itself: it will be displayed to the new hire with that.","The Due on workday field will allow you to add a workday on when the tasks needs to be completed. New hire's will get a notification of that in Slack/Webportal. Remember: this is workdays, not calendar days. If Monday is day 1, then next week Monday is day 6!","Then we have the Tags part. This is just a means of identification for yourself and other staff members. Totally optionally, but just something for you to separate tasks that have the same name. New hires will never get to see the tags.","The content is basically a WYSIWYG editor that allows you to add various things. Such as headers, lists, files and images. You can even create forms in these if you would like to get some info back from the new hire.","At the very bottom, you have a quick check box (only available with Slack integration), which is currently checked. This means that the answers from the new hire will be sent back to the Slack channel that you specify there. It's best to make the new hire aware of this, so they don't add anything they wouldn't want to share with the rest of the team. This feature is perfect for when you want to let your new hire introduce to the team with a default format."]},{"l":"Resource items","p":["Resource items are meant to inform your new hire. Think of general procedures, how to use specific tools etc. Resources look like this (for you):","resources edit","We already covered the title, tags and content part - they are the same as with the todo/preboarding items. Something new here is the 'Chapters' part. The name already gives it away, you can create chapters in these resources. This comes in handy when you want to split information a bit more (in the event that headers aren't enough). By default, you can't really check if the new hire indeed read/understood what was in the chapter. To solve that, you could turn the resource into a course (see the switch 'Is a course item'). If you enable that, your new hire will have to go through the resource chapter by chapter. You could also add questions in between the chapters, so you can check their knowledge. You will be able to see the answer that they filled in on your side. The chapter with a question mark icon before it are these test. They can only consist of multiple choice questions. You can also pick or create a category to separate the multiple resources for your new hire."]},{"l":"Introduction items","p":["Your new hire is new to the company and they barely know anyone. Perhaps they know a few people through the interviews, but that's most likely it. Introduction items are items that introduce your colleagues to your new hire. They look like this for you:","introduction edit","On the right side, you have an example of how it looks for your new hire (in the webportal). Please note that items within the curly brackets, those will be replaced with the new hire's first name. This goes for most fields in the software (including content and title items). You can use these placeholders (within curly brackets):","first_name: new hire's first name","last_name: new hire's last name","email: new hire's email address","position: new hire's position","department: new hire's department (if any)","buddy: new hire's buddy's full name","buddy_email: new hire's buddy's email address","manager: new hire's manager's full name","manager_email: new hire's manager's email address"]},{"l":"Badge items","p":["Badges are a way to keep your new hire motivated. You can't really do much with a badge, it's just there to give your new hire that extra bit of positivity between going through all the boring tasks they need to complete.","badge edit"]},{"l":"Admin to do items","p":["Sometimes, you or any of your colleagues need to do something for your new hire as well. With these items, you can automatically create a to do item for someone. You can assign it to someone and you can also notify someone else of this.","admin todo edit","They will get a notification of this through Slack or email."]},{"i":"textslackemail-messages","l":"Text/Slack/Email messages","p":["I am going over those all at once as they all have the same purpose: Sending a one-off message to someone. This 'someone' could be the new hire themselves, the manager or buddy assigned to the new hire or some random person that you can pick yourself (or in the case of Slack; a channel is possible as well).","Here is an example of an email message:","admin todo edit","Here is how the bottom part of our sequence looks like now. Now, this is only a really small sequence and you can make those as large as you want. You could also stack them - adding multiple sequences to one new hire.","sequence end"]},{"l":"People","p":["Everyone that is in ChiefOnboarding is listed under 'People' -> 'Employees'. Those include all new hires, administrators, people with no access to the dashboard and people that have limited access to the dashboard. Let's break it down a bit more:"]},{"l":"Administrators","p":["Administrators are people that have full control over the dashboard. They can create new hires, remove them, create sequences and templates and so on. You can create as many as you would like."]},{"l":"Administrators with limited access","p":["Optionally, you can add people with limited access. They have access to their new hire's (being the manager), the templates/sequences and their admin to do items. They will NOT have access to settings items."]},{"l":"Employees","p":["Employees are basically empty accounts. They don't do much by default. They will show up on the colleagues page, but that's basically it. You can import them from Slack to quickly have them all listed here.","If you want, you can assign resources to these people and then they will be able to use the Slack bot and online webportal too look into these. Resources don't have to be just for new hires - they can be useful for long time employees as well. The colleagues page will be accessible for them too then."]},{"l":"New hires","p":["You can create new hires in three different ways:","Filling in the form in the dashboard","Using the API","Automatically adding new hires when they join Slack (with or without manual approval)"]},{"l":"Filling in the form","p":["new new hire","Let's look at each form field:","First name: The new hire's first name","Last name: The new hire's last name","Email: This is the email address from the new hire - the corporate one","Phone number: This is the new hire's phone number (used to send sequence text messages to or preboarding page invitations)","Position: This is the new hire's position or title. Only used for introducing the new hire","New hire's starting date: The day the new hire starts working.","What can you share about this new hire?: This is the message that will be send to the team to introduce this new hire. Colleagues will be able to leave a personal welcome message if they want to.","New hire's timezone: Mainly used by the slack bot, but also for sending some emails. No one likes getting messages in the middle of the night.","Language: We currently support English, Dutch, French, German, Turkish, Portuguese, Spanish and Japanese. Please note that language support is still under development - some parts might not be translated properly yet.","New hire's buddy: This is the new hire's buddy, you can use this field for sending messages in the sequence.","New hire's manager: This is the new hire's manager, you can use this field for sending messages in the sequence.","Sequences: This is the part where you can assign your pre-made sequences to the new hire. If some items won't be triggered (because you created the new hire later than the first item in the sequence), then you will git a popup asking if you want to trigger those items immediately.","Once created, you can choose to send the new hire's preboarding email. This one is not sent automatically, as you might want to make changes before you send it (this will be implemented as part of the sequences later on though)."]},{"l":"Using the API","p":["Please go to the API doc page for instructions on how to set this up."]},{"i":"automatically-adding-new-hires-when-they-join-slack-with-or-without-manual-approval","l":"Automatically adding new hires when they join Slack (with or without manual approval)","p":["In the settings, there is now the option to enable 'automatic new hire creation from people joining Slack'. When a new hire joins Slack, ChiefOnboarding will get notified and it will automatically create a new hire account for them. It will also assign one or more default sequences to the new hire. No manual action is needed here - everything is automated.","Optionally, you can also enable another setting that sends you a message to manually allow/deny a new hire account. When a new hire joins Slack, you (or someone else) would get this message:","new new hire","If you click on 'Yeah!', then you will get a popup where you can choose the sequences you want to assign to them."]},{"i":"new-hires-slack-bot","l":"New hire's Slack bot","p":["An introduction in Slack will look like this:","As you can see there, they can pick any chapter they want.","Courses will look like this:","Forms work within Slack as well, with the exception of upload fields. When you use an upload field, we will redirect the new hire to the website to complete this (they don't have to login for this).","introduction slack","new new hire","Resources look like this:","slack course","slack daily reminder","slack resource","They can't skip through lessons, they will have to complete them one by one, before it's marked as done. Once a course is done, it will turn into a resource, so new hires can look through them even after they completed it.","They will be able to leave a personalized message for the new hire. This will show up on their pre-boarding pages as an extra page with all the messages from colleagues.","This is the first welcome message that is being sent to your new hire when we found the new hire in your slack team (we check every 15 minutes if there are new people in Slack, so it could take up to 15 minutes to find your new hire). You can customize this message of course to anything you like. The buttons are also optional. Along with the message, it adds the to do items that are due for that day. These are mainly to do items that are added under the 'unconditioned block' (see sequences above). Items that are added later, will be send to the new hire around 8am in the morning. The new hire will be notified for new to do items and to do items that are due (or even overdue).","todo form slack","When a new person is added, the bot will send a message to the team letting them know someone is starting soon. introduction new hire","You can customize the bot however you like. Use your own name for it and profile picture, so please ignore the current name / profile picture of the bot in the pictures below."]},{"i":"new-hires-web-portal","l":"New hire's web portal","p":["Now, most people will use the Slack integration. The web portal is more of a fallback to when a specific team in the company isn't using Slack. You can use the Slack integration standalone, but you can also use the web portal standalone. Both have all features. It's not recommended to mix them up as the Slack bot might have to do items that might have been completed already in the web portal. But, ultimately, it's up to you to decide.","The to do area looks like this:","new hire portal todo","A specific resource could look like this:","new hire portal resource","Resource that are being used as courses can contain questions and that looks like this:","new hire portal questions","You are able to view the answers in your dashboard.","There is a colleagues page that your new hires (and also colleagues that have been with you for longer) can visit to see everyone.","new hire portal colleagues"]}],[{"l":"Deployment","p":["Currently, three ways of deploying are supported out of the box. Docker, Render and Heroku.","Deploy with Docker","Deploy with Render","Deploy with Heroku","Once you have set one of them up, you will need to follow the next steps to set up storage, email, text messagea and more!"]},{"l":"Deploy with Docker","p":["You can easily deploy ChiefOnboarding with Docker (Docker-compose). Make sure that both Docker and Docker-compose are installed and your server. Please note that some of the data below contain example values and should be replaced.","Point your domain name to your IP address.","Create a folder somewhere and then add this docker-compose.yml file (change the environment variables to something that works for you!):"]},{"i":"21-caddy-based-deployment","l":"2.1 Caddy-based deployment","p":["If you don't want to have a secure connecting and want to connect over http(not secure, and you will have to change the Caddy file below), then add HTTP_INSECURE=True to your environment variables.","2.1.1 Then we need to create a Caddyfile to route the requests to the server (change the domain name, obviously):"]},{"i":"22-non-caddy-based-deployment","l":"2.2 Non-caddy-based deployment","p":["This method may make it easier to deploy on a server that is already configured with an existing web server (e.g., Nginx, Apache, etc.) You will need to install Cerbot to configure LetsEncrypt. This approach assumes that you will be configuring a reverse proxy on port 8888.","You can now run docker compose: docker-compose up. When you go to your domain name, you should see a login form where you can fill in your username and password (either from the logs, or specified yourself). There will be some demo data in there already, feel free to delete everything.","Note: if you need to do a healthcheck for your container, then you can use the url /health for that. This url is available under any IP/domain name. It will respond with a 200 status and an ok as content. The ALLOWED_HOSTS variable is ignored for that url."]},{"l":"Update docker image","p":["Please make a backup of your database before doing this.","First stop all containers: docker-compose down","Pull the new image: docker-compose pull","Start the containers: docker-compose up -d"]},{"l":"Deploy with Render","p":["You will have to login to Render or create an account there. Then, you will need to click this link to start the process: Deploy to Render","You will then need to fill in the following details:","ALLOWED_HOSTS: This needs to be the domain you want to use for the platform. Either your Render subdomain or your own subdomain. You can add multiple urls if you want to make it available with multiple urls (example: domain.example.com,domain2.example.com). Do not add the protocol ( https://) before the url. If you don't have a url, use test.chiefonboarding.com and change it later to your xxxx.onrender.com link.","Click on deploy and let it run. This will take about 10 minutes before it's ready, though it could take a few hours, so be patient please.","If you DO have a domain name:","Go to the chiefonboarding service and go to settings. Scroll down until you see the Custom domain setting. Add your domain there and configure your DNS to link to it.","If you DO NOT have a domain name:","Go to environment variables and swap the ALLOWED_HOSTS and BASE_URL with the url that has been given to you by Render. Wait for it to automatically redeploy.","That's all!"]},{"l":"Deploy with Heroku","p":["ALLOWED_HOSTS: This needs to be the domain you want to use for the platform. Either your Heroku subdomain or your own subdomain. You can add multiple urls if you want to make it available with multiple urls (example: domain.example.com,domain2.example.com). Do not add the protocol ( https://) before the url.","Click on Deploy app. You should see this when it's done (this might take a few minutes):","heroku click recheck","heroku deploy done","heroku new domain","heroku settings domain","If you are using a custom domain: go to the settings area and look for the 'domains' part:","Please note: you will need to have an account at Heroku for this to work. Hosting at Heroku is more expensive than hosting it with Docker on a VPS. We will set it up to use two Hobby Dynos (which will be $14/month). A database upgrade might be necessary later on.","SECRET_KEY: You can't change this and shouldn't. It will be generated by Heroku. It's used for signing cookies, encrypting data etc.","SSL_REDIRECT: Leave it at True. This is used to redirect all traffic from http to https.","That's all!","The app name can be anything you want (so long it is available).","Then click on 'Add domain' and enter your domain name. You will get a DNS target to point your domain name to in your DNS settings:","Under \"config vars\" you will have 5 items. Before you fill in anything: decide whether you want to use a Heroku subdomain app name.herokuapp.com or your own domain onboarding.yourcompany.com. Your own domain doesn't have to be a subdomain.","You might get a red icon now next to your domain name. It might take a bit of time to get your domain validated (DNS is often cached). Just wait for a bit and try to refresh it until it becomes green:","You will have to login to Heroku or create an account there. Then, you will need to click this link to start the process: https://heroku.com/deploy?template=https://github.com/chiefonboarding/ChiefOnboarding. Heroku will then ask you for some details. Please be careful to put them in correctly, otherwise your app will not start."]},{"l":"Update Heroku","p":["Please make a backup of your database before doing this.","Install the Heroku CLI and authenticate yourself.","Download the ChiefOnboarding git repo: git clone https://github.com/chiefonboarding/ChiefOnboarding.git","Add your heroku git url as a git remote. You can find this url on the app's settings page -> app info -> Heroku git URL. git remote add heroku_repo repo_url(replace repo_url with your own url).","Then push it up: git push heroku_repo master"]},{"l":"Next steps","p":["As of right now, your ChiefOnboarding instance will be up and running. Though, it might not be fully functional yet. There might be some components that you want to add, like email, object storage (saving files), text messages or the Slack bot."]},{"i":"object-storage-updownloading-files","l":"Object storage (up/downloading files)","p":["Add this CORS configuration there (change YOURDOMAIN):","Add your newly created policy to the user and click on 'Next'.","Caddyfile","Click on 'Add user'.","Click on 'Add'.","Click on 'Next' again. Twice.","Click on 'Review policy'.","Click on your newly created bucket.","Example variables:","For 'Actions' pick 'GetObject', 'DeleteObject' and 'PutObject'.","For 'Service' pick 'S3'.","Give it a fancy name and click on 'Create policy'.","Give it a fancy name and click on 'Next'.","Give it a fancy user name and select 'Programmatic access', so we get the keys we need to enter in ChiefOnboarding. Click on 'Next'.","Go back to the set up screen of your IAM user and click on the refresh button to refresh policies.","Go to 'Attach existing policies directly' and click then 'Create policy'.","Go to https://console.aws.amazon.com/iam/home#/users.","Go to https://s3.console.aws.amazon.com/s3/home and click on 'Create bucket'.","Here is a step-by-step for AWS:","If you want to use Minio (self-hosted), then you could use something like this as an example for both ChiefOnboarding and Minio:","In the bucket, go to 'Permissions' and then to 'CORS'.","Keep everything at the default (or change it to your liking) and click on 'Next'.","Keep everything at the default and click on 'Next'.","Note that you might still need to set some of the environment variables below (such as the bucket).","The bucket is now created. Up next, we need to create a user to be able to post and get from this bucket.","The instructions below will set everything up by using client/secret token. You can also use a profile/role if you prefer. Under the hood, ChiefOnboarding uses boto3, which means that it will search for credentials by itself as well. Please see the documentation for those boto3 environment variables here: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html","Under 'Resources', enter the correct bucket name and for the 'Object name' select 'Any'.","You can use AWS S3 for this, but you are also free to use any other provider who provides the same API. For example: Wasabi, Vultr, Digital Ocean, or Fuga cloud.","You will now get to see the Access key ID and the Secret access key. Add those to your environment variables or .env file."]},{"l":"Email","p":["If you want to send emails to anyone, then you will need to add a provider. Technically, if you are using a VPS, you could start selfhosting your own SMTP server, however we recommend against that. In any case, you need to set up the email environment variables if you want to start sending any emails.","ChiefOnboarding is using the django-anymail package to support a wide variety of email providers(Sparkpost is not supported in ChiefOnboarding).","If you want to enable emails (this is highly recommended), then you will first have to set the from email and choose one of the providers below or go with SMTP and use pretty much any provider.","Example for the email header variable:","Email providers:","Postmark:","Mailgun","Mailjet:","Mandrill:","SendGrid:","Sendinblue:","SMTP:","For SMTP, you only need to set either EMAIL_USE_TLS OR EMAIL_USE_SSL to True. If you set both, then it will likely not send out any emails."]},{"l":"Custom email template","p":["You can set your own email template if you want. You can see the default one here: https://github.com/chiefonboarding/ChiefOnboarding/blob/master/back/users/templates/email/base.html","Some things are rendered dynamically. You can use this as an example:","Don't change whatever is within the brackets. Feel free to customize everything around it however you would like!"]},{"l":"Ratelimits of failed login attempts","p":["By default, ChiefOnboarding uses allows users to attempt 10 times before the user gets blocked by IP. You can change the defaults:","AXES_ENABLED: Default: True. Set to False if you want to disable blocking users from trying again (not recommended).","AXES_FAILURE_LIMIT: Default: 10. Sets the amount of attempts before user gets blocked.","AXES_COOLOFF_TIME: Default: 24(in hours). After 24 hours the IP address gets cleared again.","AXES_USE_FORWARDED_FOR: Default: True. In many cases ChiefOnboarding is deployed behind a proxy (i.e. Docker or Heroku reverse proxy). This allows you to get the IP address from the refer header. Without this, it would log internal ip addresses, which means that users will share the same ip address and get locked out unintentionally."]},{"l":"Text messages","p":["If you want to start sending text messages to new hires or colleagues, then you will need to signup with Twilio and get a number there.","Sign up at Twilio if you haven't yet.","Go to https://www.twilio.com/console/phone-numbers and click on the red 'plus' icon.","Pick a number you like and purchase it. Make sure it allows text messages.","Go to https://www.twilio.com/console/project/settings","You can take the account_sid and api key from there and add those to your environment variables or .env file.","Example variables:"]},{"l":"Error logging","p":["This is entirely optional, but if you want to catch errors comming from your instance, then Sentry is ready to be used for that. No system is ever bug-free. Errors happen. This is really useful if something happens with your instance and you want to give us a detailed log about it. You can share the error log and we can then fix it much quicker. Obviously, we are not connected to your Sentry account, so you will have to let us know about it!","You will have to provide a URL to send the requests to. This URL may be from the hosted version of Sentry or the on-premise one. Both will work just fine.","Go to sentry.io","Sign up and then create a new 'Project'.","Select 'Django' and give it a name.","Copy the value of the DSN url. Example: https://xxxxxx.ingest.sentry.io/xxxxxx.","Example variable:"]},{"l":"Google SSO","p":["This will allow you to use the 'Log in with Google' button on the log in page.","Go to https://console.developers.google.com/apis/consent and make sure you are logged in as the admin of the Google organization.","Create a new 'Project' and give it a fancy name. Once it's created make sure you are in that project (you can see that in the top bar).","You will be asked for what type of app you want to register. Choose 'Intern', only people from your organization should log in to your app. Click on 'Create'.","Fill in the details accordingly. You don't have to change the scopes, those are fine. Under 'Authorized domains', fill in your own site url and the url of the ChiefOnboarding instance.","Click on 'Create'. You will be taken back to the page you previously landed on.","We just set up our authentication screen for people that want to sign in. Up next, we need to create credentials that we can put into the ChiefOnboarding instance, so we can actually show that authentication dialog.","Go to https://console.developers.google.com/apis/credentials","Click on 'Create credentials' at the top of the page and choose Client-ID OAuth.","You will be asked for the type of app. Pick 'Web application'.","Under \"Authorized JavaScript-sources\" enter the domain name of where ChiefOnboarding is running on.","Under \"Authorized redirect-URLs\" enter this: https://YOURDOMAIN/api/auth/google_login.","Click on 'Create' and you will get the Client-ID and Client-secret that you need to fill in on your ChiefOnboarding instance.","Submit the form on ChiefOnboarding and enable the Google login integration in settings->global and you should be good to go.","You will only be able to let people log in who already have an account in ChiefOnboarding."]},{"l":"Slack bot","p":["This is the bot that will ping your new hires and colleagues with things they have to do. This is needed if you want to use ChiefOnboarding in Slack. Since there is no centralized app, you will have to create an app in Slack yourself. The benefit of this is that you can use your own profile picture and name for the bot.","Manifest (webhook) - replace XXX with your domain name:","Go to https://api.slack.com/apps and click on 'Create New App' (big green button, can't be missed). Click on \"From an app manifest\".","Select the workspace where you want to install ChiefOnboarding.","Copy and paste the manifest in the little text box.","Review the permissions and then click on 'Create'.","Scroll a bit on the new page and notice the App credentials part. You need the information there to fill in on the settings/integrations page in your ChiefOnboarding instance.","Fill in the details accordingly.","Submit the form. You will now get a \"Add to your Slack team\" button. Click it and verify that you want to install your bot in your Slack team.","Go back to your Slack bot and go to \"App Home\". Then scroll down till you see: \"Show Tabs\". Enable the \"message tab\" and check the \"Allow users to send Slash commands and messages from the messages tab\".","That's it!"]},{"i":"oidc-single-sign-on-sso","l":"OIDC Single Sign-On (SSO)","p":["To enable OIDC, you must enable \"Allow users to login with OIDC\" in the admin settings page at https://example.com/admin/settings/general/.","You may need the redirect URL for your Identity Provider (IdP). The REDIRECT_URL should be set to https://example.com/api/auth/oidc_login.","If you set OIDC_FORCE_AUTHN=True, the login page will automatically redirect to the OIDC IdP."]},{"l":"Role Mapping","p":["In this example, we use CAS as the IdP and modify the zoneinfo field to display group information. You can see OIDC_ROLE_PATH_IN_RETURN='zoneinfo' is set accordingly.","If your groups (roles) are stored deeper in the JSON structure, like:","You can set OIDC_ROLE_PATH_IN_RETURN='B.roles' using dots.","There are three patterns to map ChiefOnboarding's role with OIDC_ROLE:","For Admin, apply OIDC_ROLE_ADMIN_PATTERN to OIDC_ROLE","For Manager, apply OIDC_ROLE_MANAGER_PATTERN to OIDC_ROLE","For Newhire, apply OIDC_ROLE_NEW_HIRE_PATTERN to OIDC_ROLE","OIDC_ROLE_DEFAULT is used to set other users' roles; you likely don't need to change it. If you don't want to use role mapping, simply leave it as a space.","If you do not want the OIDC provider to update roles, then you can disable it by setting OIDC_ROLE_UPDATING to False."]},{"l":"Logout","p":["Since this is an SSO implementation, we recommend setting OIDC_LOGOUT_URL. When you log out, it will redirect to the OIDC_LOGOUT_URL.","Here's the updated configuration example:"]}],[{"l":"Development","p":["If you want to contribute or just play around with the source code, the first step would be to download the source code. Then run this to get it all up and running:","Please note that it could take a few seconds everything is set up. Ignore any error messages you see, this is generally because the database hasn't been migrated yet. It will do that at the end automatically.","Once it's ready, go to http://0.0.0.0:8000 and you should see the setup screen. Fill in the details and you will get a bunch of dummy data as well!"]},{"l":"Enable better logging","p":["If you want to start developing/debugging and need more verbose log messages, then you can enable debug log messages with this environment setting:"]},{"l":"Adding a new language","p":["If you want to add a new language, then you will have to follow these steps:","Replace lang with the shortname of your language (e.g. nl, en, or es) in the command below","It will generate a new file for you to fill in. It's a .po that you can edit (with a text editor or through one of the many tools).","Up next, you will need to add the language to the list of languages. Go to back/back/settings.py and add your language to this array https://github.com/chiefonboarding/ChiefOnboarding/blob/v2.0/back/back/settings.py#L371. That way, it will show up in the lists to choose the language."]},{"l":"Updating existing translations","p":["Simply run this command and it will update all current translations:"]}],[{"l":"Architecture","p":["ChiefOnboarding is build on top of Django (Python). It's mostly a \"boring\" app in the case that we don't use any type of frontend framework to decouple the frontend from the backend. It does use some sprinkles of JavaScript to create some moving elements. There is some HTMX, VueJS, jQuery, Bootstrap JS and a few other scripts.","A few things you should know about ChiefOnboarding:","It uses Pytest for testing the code. For object creation, it uses factoryboy. You will find factories.py in almost every app.","It relies heavily on background tasks. You can find those tasks in the tasks.py files in the apps folders. Especially the Slack bot and the Sequence s use those a lot.","Supervisord is set up for docker-compose. It will run two processes: the background worker ( Django-Q) and python manage.py runserver for the server.","Sequences are basically blueprints for new hires. The Condition s that are in there are all connected to the Sequence. Once a sequence gets assigned to a new hire, it will duplicate the Condition and assign it directly to the User model. This means that if an admin would change a Condition in a Sequence, then that won't affect new hires that are currently going through sequences. There is one caveat with that though: if a template gets changes (i.e. a to do item or resource), then that will reflect for all people that don't have a custom one. Once you make changes to a template in a sequence, then it becomes a custom item and those items will not update when you update the original one.","Here is an overview of the database models of ChiefOnboarding:","ChiefOnboarding models"]},{"l":"Folder structure","p":["In the root of the repo, there are a bunch of files and folder. The files are mostly there for deployment and development. The bin folder is purely for Heroku to generate the messages necessary for enabling multilanguage.The .github/workflows folder probably speaks for itself, that's for running workflows (tests, deploy to Docker, etc). The docs folder represents all the docs that are shown at https://docs.chiefonboarding.com. The back folder is where the actual application lives."]},{"i":"backadmin","l":"back/admin","p":["In this folder you will find only things that are mainly used by admins. These are all templates ( to_do, resources, introductions, appointments, badges, preboarding), people options ( back/admin/people/views.py and back/admin/people/new_hire_views.py for new hires), admin_tasks(things colleagues need to d for new hires), sequences, and settings(global as well as personal)."]},{"i":"backback","l":"back/back","p":["This is just the core app that Django creates by default. You will find the settings.py file in there and the base urls.py file."]},{"i":"backfixtures","l":"back/fixtures","p":["These are the default fixtures that are used for a limited part of testing and mostly for loading dummy and default data once someone installs ChiefOnboarding. This happens for both local developing and in production."]},{"i":"backlocale","l":"back/locale","p":["This is were all translations are stored."]},{"i":"backmisc","l":"back/misc","p":["This folder is pretty much used for everything that doesn't fit anywhere else. For example, uploading to object storage is used throughout the platform and isn't attached to anything specific."]},{"i":"backnew_hire","l":"back/new_hire","p":["This covers the new hire portal."]},{"i":"backorganization","l":"back/organization","p":["When someone installs ChiefOnboarding, it will create one Organization by default. You can see this as the settings model for the site. Everything that is configurable by the admins (i.e. color scheme, default email template and slack settings are all stored in the Organization. You can call the object for this everywhere, using org."]},{"i":"backslack_bot","l":"back/slack_bot","p":["This is used only for the Slack bot. For local development, there is an option to enable websocket support, though it can be a bit flaky."]},{"i":"backstatic","l":"back/static","p":["This is where all static files are stored. Things like CSS, JavaScript and images."]},{"i":"backuser_auth","l":"back/user_auth","p":["This is for authenticating the user. Be it through SSO or plain username/password. ChiefOnboarding mostly relies on the Django authentication module (and therefore uses sessions). django-axes is also installed to prevent brute-force attacks."]},{"i":"backusers","l":"back/users","p":["This is where the User model can be found. It has been put in a separate folder as the User model contains all sorts of user accounts (i.e. new hire, admin, manager). Those are differenciated through an option field on the model."]}],[{"i":"integrations--webhooks-beta","l":"Integrations / Webhooks (Beta)","p":["ChiefOnboarding allows you to create integrations or trigger webhooks that can be triggered either manually or through a sequence. You can view some examples at https://integrations.chiefonboarding.com. You are free to copy them. If you created a cool new integrations, then please post it there. That way we can help eachother out by not re-inventing the wheel! Thanks a lot!","There are two types of integrations:","An integration to trigger a URL on an third party service","An \"sync users\" integration, which allows you to import users from a third party to ChiefOnboarding (manually or through a background cron job) or update specific information to the user (for example, save an external ID per user)"]},{"l":"Integration to trigger a third party url","p":["Here is an example of a manifest of an integration (in this case to add a user to an Asana team):","Let's go over the items:"]},{"l":"Form","p":["This is the form that is shown to you when you add this to a sequence. The form should consist of items that you would like to have different for different type of people. In the example above, the form allows you to pick a specific team to add the user to. For example: you probably don't want to add a developer to the HR team in Asana. So, the team is what you can customize every time you add the integration to a user or in a sequence.","You can customize where we get the info from and what an admin should fill in. The form should always be an array and allows the following properties:","id: This value can be used in the other calls. Please do not use spaces or weird characters. A single word is prefered.","name: The form label shown to the admin.","type: options: choice, multiple_choice and input. If you choose choice, you will be able to set the options yourself OR fetch from an external url.","For choice:","url: (if you have static items, then use items instead). The url it should fetch the options from.","method: Default: POST. You can use any request method you would like.","headers: (optionally) This will overwrite the default headers.","data_from: The property it should use from the response of the url. In some cases, it might happen that what you get more than just the options you need. For example, you get a dictionary instead of an array and need to go a little deeper in the data. For example: you get a dictionary that has the prop options which has an array with the items. You can then specify options as the value for data_from and it will use that. If you need to go deeper, you can use the dot notation to do that. E.g. data.options.items. Leave this field blank if you are using predefined items.","choice_value: The value it should take for using in other parts of the integration (for example the id property of the items you get from the server). Default: id.","choice_name: The name that should be displayed to the admin as an option. Default: name.","items: (if you are not fetching items from a url) You can add an array here with objects in them with the props: id and name. For example: [{id: 233, name: option 1}, {id: 234, name: option 2}]."]},{"l":"Exists","p":["Exists is an option to check if a user is already part of a team. If you add this property to your manifest then it will show up under new hire -> access. From there, you will be able to manually enable/disable an account for them. Generally, you should skip this option if you are making any calls not related to account provisioning.","url: The url to check if the user exists. Everything that comes back is parsed to a string and then checked against.","method: The method for lookup that is being used. E.g. POST or GET.","expected: Whatever we expect. Generally this will probably be a positive message or the new hire's email. You can use new hire values by wrapping them around double curly brackets.","headers: (optionally) This will overwrite the default headers.","fail_when_4xx_response_code: Default: True. If the server response with a 4xx status code, then that's considered a failing request. In some cases, apis will return a 404 if the user does not exist. In that case, set this to False, so it can check for the expected value."]},{"l":"Revoke","p":["Revoke is an option to revoke access of a user to a third party. If you add this property to your manifest then you will be able to revoke access through the dashboard. Generally, you should skip this option if you are making any calls not related to account provisioning.","This uses the same setup as the execute part below (but is limited to url, data, method and headers). It expects an array with requests in it."]},{"l":"Execute","p":["These requests will be ran when this integration gets triggered.","url: The url where the request will be made to.","data: This is the data that will be send with it.","method: The request method. E.g. POST or GET.","headers: (optional) This will overwrite the default headers.","store_data: (optional) This can be used to store data to the new hire. Let's say you create a document through an API and you need to store the document ID that is relevant to the new hire, then you can do that with this. You can put a dictionary here with a key and value of the new hire prop name and the notation of where to get the data. You can use a dot notation to go deeper in the json. This data is only available in items assigned to this new hire and can be used anywhere (in both content items (todo, resources etc) and integrations that get triggered later).","Example:","continue_if: (optional) This can be used as a blocked. If you want to block an integration if a response is not what you expect, then you can do that with this. If you need to wait for a response to come back (waiting for a background task for example), then you can use polling and continue with the call with the response changes. It will check every response and stop polling when it matches.","With this config, it will check the response for the status property in the detail property (so for example: {detail: {status: done}}). It will check for the value done, which would be valid in this case and therefore continue with the integration.","polling: (optional) You can use this to poll a url if you are waiting for a background (async) task to be completed. It will retry fetching the url for as many times as you specify at the interval you want. Here is an example config:","This config will try to fetch the same url for 60 times and wait 5 seconds between each call (so max 300 seconds) and will keep going until the status of the response is done. If it exceeds the 300 seconds, then the integration will fail.","save_as_file: (optional) If you expect a file as a response from the server, then you can define this with the filename you want it to have. For example: save_as_file: filename.png. You can then use this filename in the files parameter for any requests that you make after this one.","files: (optional) You can use this to define what you want to send to the api as files. Note that you will have to download the files in the same integration before you are able to use this. This item needs to be defined like this:","It will search the previous responses by the key of the files dictionary. In this case that would be filename.png, so you would need to have save_as_file: filename.png in any of the previous requests."]},{"l":"Headers","p":["These headers will be send with every request. These could include some sort of token variable for authentication."]},{"l":"Oauth","p":["If you need to use OAuth2 to get a token, then you will need to use this. Just create a prop called oauth and then in that use these properties:","authenticate_url: This is the url that is used to send the user to the login/authorize the connection (this should be a url to the third party). This is always a GET request. It expects an url here.","access_token: This is used when you come back to our site with a token. With that token, it will need to fetch an access token from the third party (and perhaps a refresh token). Format is an object like the execute part.","refresh: Used to refresh the token to get a new one, if this is not added, then it will assume that the token is permanent. Format is an object like the execute part.","without_code: Default: False. Enable this is a valid callback won't return a code query in the url. In some cases, we don't get it and also not need it."]},{"l":"Initial data form","p":["This is a form that you can create to fill in when you add this integration to your instance. Any sensitive info should be filled in here, instead of in the manifest itself. Data that gets filled in here will be saved encrypted in the database. The manifest itself does not get encrypted. So, again, any tokens, authentication, sensitive info should be filled in through this form and not hardcoded!","You can obviously add as many as you want. You can use these variables by using the id in any of the other parts of the manifest.","id: Reference for any other part of the manifest. Wrap it around double curly brackets to use it.","name: The label of the field. Please do not use spaces or weird characters. A single word is prefered. Use generate to generate a secret value, use this for i.e. one-time password.","description: Any other info you want to leave to make it clear where to find this value. Mainly used for documentation and/or sharing."]},{"l":"Post execute notification","p":["Defined as post_execute_notification. Gives you the ability to send a text message or email to someone after this integration has been completed.","type: Either email, or text. Depends if you want to send an email or text message.","to: Use a fixed email or (preferably) a placeholder.","subject: In case of an email, define the subject header.","message: The message that should be send (plain text)."]},{"l":"Variables","p":["Throughout the manifest you can use the variables that you have defined in the initial_data_form or the form wrapped around in double curly brackets. On top of that, you can also use new hire values. You can use:","email: New hire's email address","manager: The manager's full name","manager_email: The manager's email address","buddy: The buddy's full name","buddy_email: The buddy's email address","position: New hire's position","department: New hire's department","first_name: New hire's first name","last_name: New hire's last name","start: New hire's start date","access_overview: This will be a list of all the access the user could have access to. This includes previously assigned manual access and automated access (all of the automated items). It will result in a string like this: Asana (no access), Google (has access), Teams (unknown). unknown is used when we couldn't reach the service.","Please do not overwrite these with your own ids","You can also use data from previous requests. If you have an integration with 3 requests, you can use the data from the request 1 in request 2 and the data from request 1 and 2 in request 3. You can do that by using: {{ responses.index.the_data_you_need }}(index starts at 0). So for example, you get this response from the first request:","You can then use {{ responses.0.form_id }} in any of the following requests in the same integration."]},{"l":"Notes","p":["If triggering an integration fails, then it will retry the entire integration again one hour after failing. If it fails again, it will not retry.","If you are using any of the integrations from the repo at: https://integrations.chiefonboarding.com then you have to validate them yourself. This is a user repository and we do not actively moderate the submissions there. Please always validate the urls where requests are going to make sure it's legit."]},{"l":"Sync users integration"},{"l":"Creating users","p":["You can create custom import integrations to pull users from a third party and put them in ChiefOnboarding. This is fairly universal and will work with most APIs. A sample integration config will look like this:","The setup is very similar to what we have for other integrations to trigger a webhook. The most notable differences are:","data_from: this is to indicate where the users are located in the response. You can use a dot notation if need to go deep into the json to get the data.","We then also need to define where the data is stored in the users array (for each object). We can do that with data_structure. In there, you can define the values you want to copy. Please note that only email, first_name and last_name can be used for now.","So for the current config, we expect a JSON response from the third party like this:","Other values in the JSON will be ignored.","You can run this integration manually (by going to people -> colleagues -> import... \". If you provide a \"schedule\" prop (cron notation), then it will run this in the background. It will create the users automatically (default role is \"other\")."]},{"l":"Updating users","p":["This will allow you to save additional data from a third party to your user. This can be helpful in case you need a specific ID in an integration that is tied to this user for example. You cannot update core attributes of a user (such as their email or first name). You can only save extra information to the user, which can then be used in integrations or content boxes.","An example integration to save the bambooHR user id to the user in ChiefOnboarding:","The schedule prop is mandatory here as it would otherwise never run, you cannot trigger this manually. The other main difference with the import option is the \"action\". It's \"update\" in this case. You will also have to provide the email key in the data_structure, so ChiefOnboarding knows how to match the user. If no user can be found with the provided email, then it will get skipped."]},{"l":"Paginated response","p":["Sometimes, we might not get all items at once. We have something to cover that too. This only works for syncing users and importing users.","amount_pages_to_fetch: Default: 5. Maximum amount of page to fetch. It will stop earlier if there are no users found anymore. There is a limit to this number. Please see the note below.","There are two ways of fetching a new page:","Sometimes an API will only return a token and we will have to build the url ourselves. (Google does this for example)","In most cases, you will get a full url that you can use to fetch the new page of users.","For case 1, you will need to provide two items (the url and where the token is):","next_page_token_from: the place to look for the next page token. You can use the dot notation to do go deeper into the JSON. If it's not found, it will stop. next_page: This should be a fixed url that you should put here. You can use {{ NEXT_PAGE_TOKEN }} as the variable to include the previously found next_page_token_from value.","For example, this is necessary for Google:","For case 2, you will only need to provide the place where we need to look for the URL with this item:","next_page_from: the place to look for the next page url. You can use the dot notation to do go deeper into the JSON. If it's not found, it will stop.","Note: fetching users is being done live when you visit the page. If you set a high amount of pages to be fetched, then this might cause a timeout on the server. It makes rendering all users on the client also very sluggish. We recommend to not load more than 5000 users or not more than 10 pages (if a timeout of 30 seconds is set on your server (like Heroku for example)), whichever comes first. If you do need more, then we recommend going for an alternative method of importing users."]}],[{"l":"API","p":["This API will allow you to programmatically create new hires. The API does not work when you are logged in with sessions (logging in through the log in form), you will need to use a token to get access. These tokens do not expire and you can create them through shell."]},{"l":"Setup","p":["Enable the API through the environment variable:","Just to be safe, run the migrations for the token table docker-compose run --rm web python3 manage.py migrate(docker) or redeploy on Render/Heroku. Up next, you will have to generate a token to authenticate with the API. You will have to attach a user to it, like this:","Use the email address from an admin user there. You will then get to see the newly created token. Now you can make calls to the API. Please note that if you ever remove this person, then the token will also be revoked.","Example:"]},{"l":"API usage example"},{"l":"Adding a new hire","p":["We would like to assign a buddy to this new hire, so first we need to get a list of employees to find the id of our buddy. Getting all employees that are in ChiefOnboarding:","We might also want to add some sequences to the new hire. In that case, we need the ids of the sequences we want to add. We can get all sequences with this request:","Create the new hire:","first_name, last_name, role and email are required","Role options (note: keep an eye on updates, this will likely change soon):","0: new hire","1: administrator","2: manager","3: other (user will not get notified and does not have any meaningful permissions, no slack connection either)","The data part of that query (with explanation):","It will return the full new hire object including the ID of the new hire."]}],[{"l":"Changelog"},{"i":"v200","l":"v2.0.0","p":["API has breaking changes. Please see the dedicated API page for that.","Assign admin tasks in sequence to admin/manager instead of a specific person","BREAKING CHANGES:","Buttons posted in Slack before this migrations might become invalid.","Change admin to manager and vise versa","Change channel where bot sends messages to","Change email template","Completely new look","Docs have been updated and moved to the ChiefOnboardig repo (instead of a standalone repo)","Google account creation will be temporarily removed. Record will still be in the database and will be available for use when we create this integration again. You could also remove this integration before migrating if you want to.","Moved from SPA back to MPA (dropped almost all javascript requirements)","Notifications on both the new hire and admin side on various actions","Scheduled access items that have been scheduled on the old version will not be executed anymore - table is dropped and functionality has been replaced","Selectboxes have been dropped temporarily from forms. Those will be gone after migration.","Sequence timed based triggers can now be triggered at a custom time (used to be always at 8 am)","Slack account creation will temporarily be removed. You can add it back when you go to our integrations site (see above). If you need the old key, then you can find it in Slack under your apps list (api.slack.com).","SLACK BOT: Under \"Interactivity & Shortcuts\" in the config of your bot ( https://api.slack.com/apps), change \"callback\" to \"bot\" in the URL. It should now be the same URL as you have under \"Event Subscriptions\". You will also need to change the redirect url. Change \"api\" to \"admin\" in the url and save it.","Slack doesn't need to depend on webhooks anymore - websocket is now supported as well (so you can also use it without having a public access point).","Some urls will not be accessible (like preboarding links). I am not setting up a redirect for this. These will return 404.","Support for custom integrations and webhooks created by you ( https://integrations.chiefonboarding.com/ https://github.com/chiefonboarding/ChiefOnboarding/blob/v2.0/docs/Integrations.md)!","You can update Slack to use the internal websocket instead of the HTTPS calls webhooks. That way, you remove one open endpoint (technically, you could use the app now with Slack behind a VPN). Webhooks is the default as we have noticated that they are more stable."]},{"i":"v1223","l":"v1.2.23","p":["Fix email default from field for password reset","Fix not being able to remove external messages (slack/email/text)"]},{"i":"v1222","l":"v1.2.22","p":["Fix related to v.1.2.20"]},{"i":"v1221","l":"v1.2.21","p":["Bump Django version"]},{"i":"v1220","l":"v1.2.20","p":["Fix bug with sending custom email (replacing variables)"]},{"i":"v1219","l":"v1.2.19","p":["Fix render database not in same region as app"]},{"i":"v1218","l":"v1.2.18","p":["Remove DO as DO won't work with Django Q (no support for multiprocessors). For reference: https://www.digitalocean.com/community/questions/app-platform-multiprocessing-python?answer=69003","Fixed Render to work with supervisor setup (no need to create an extra worker).","Fixed Docker hub link."]},{"i":"v1217","l":"v1.2.17","p":["Forcing Python 3.7 to avoid SemLock error on DO/Render"]},{"i":"v1216","l":"v1.2.16","p":["Django version update","Fix resources in Slack"]},{"i":"v1215","l":"v1.2.15","p":["Limit auth with url only to new hires","Fix missing import","Fix Slack authentication bug"]},{"i":"v1214","l":"v1.2.14","p":["Remove google delete user"]},{"i":"v1213","l":"v1.2.13","p":["Add deploy to DigitalOcean button","Add deploy to Render button"]},{"i":"v1212","l":"v1.2.12","p":["healthcheck url + allowed hosts fix","Update docker image number"]},{"i":"v1211","l":"v1.2.11","p":["additional update regarding v1.2.10"]},{"i":"v1210","l":"v1.2.10","p":["Update slack add bot redirect button - remove legacy bot permissions"]},{"i":"v129","l":"v1.2.9","p":["Fix bug with adding introduction/appointment items"]},{"i":"v128","l":"v1.2.8","p":["Remove old signals file (old setup)","Fix not being able to add to do items through 'add sequence' button","Fix showing empty 'to do' conditions on new hire timeline"]},{"i":"v127","l":"v1.2.7","p":["Adding default username/password to dev docker-compose file","Adding migrate cache table to dev docker-compose file","Adding node_modules to gitignore","Updates for Django Q. Stop having it redo every failing task indefinitely."]},{"i":"v126","l":"v1.2.6","p":["Show error message when trying to send Slack test message without Slack account attached","Fix showing preboarding preview part in a sequence","Fix Slack syncing issue","Update Django dep to newest version","Update Docker version number (routine task)","Fix showing old data in sequences (when adding a new one)"]},{"i":"v125","l":"v1.2.5","p":["Fix docker copy command"]},{"i":"v124","l":"v1.2.4","p":["Simplify docker setup (remove folders that are not necessary in container)"]},{"i":"v123","l":"v1.2.3","p":["Putting new hire start date further in the future (fixtures)","Fix for blocking collectstatic on restart of container","Enforcing email address of admin account to be lowercase. The email address would always be registered as lowercase and could therefore output incorrect info (on first run - creating admin account).","Updated Docker version"]},{"i":"v122","l":"v1.2.2","p":["Another docker build fix"]},{"i":"v121","l":"v1.2.1","p":["A docker build fix"]},{"i":"v120","l":"v1.2.0","p":["TOTP 2FA support. You can now use andOTP, Aegis authenticator, Google authenticator, Authy or any other OTP app that you use to set up 2FA (with QR code).","New editor and video support TipTap. We now support native video upload to S3. It will show up as a video in the portal and as a normal link in Slack.","SMTP support","Refactor Docker setup. Swapping Celery with Django Q. All running with supervisor now. Redis is now deprecated."]},{"i":"v110","l":"v1.1.0","p":["Docker image","Heroku deployment"]},{"i":"v100","l":"v1.0.0","p":["Automatically add new hires when they join Slack (optionally)","Subject to custom email message. Used to be \"Here is a quick update\"","Default sequences. Sequences that are always added to new hires by default."]}]]
\ No newline at end of file
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index 599ad8b12..c1fb86c67 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ