Display a waiting screen for the exact duration of a long automation / Make scenario with ChatGPT or else

Hi all!

Currently, all of the snippets to generate a waiting screen while the data is being processed in make or in an Airtable automation relied on a static duration (setTimeout).

The following code allows to display a waiting screen with a dynamic duration. It means that the waiting screen will only last the exact time of the data process in Make or elsewhere.

Few words about my current setup (you can check it in the Gif below, to be more visual).

  • A list details block to catch the right recordId
  • A form block to send the record of the list-details block to Make.
  • A list block gathering different records including the one in the list-details block

ezgif-1-90c8d68d87

The code relies on a mutation observer. Another version might be released in the next few weeks so the code relies on a data flag.

Here is the full code, to be inserted in the custom code header of the page settings:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">

<div id="loading-screen">
  <div class="loading-content">
    <p>Your xxxxx is being created. Patience...</p>
    <i class="fas fa-spinner fa-spin loading-spinner"></i>
  </div>
</div>

<style>
  #loading-screen {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #4893eb;
    z-index: 9999;
  }

  #loading-screen .loading-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    text-align: center;
    font-size: 20px;
    font-weight: bold;
  }

  #loading-screen .loading-spinner {
    font-size: 40px;
    margin-top: 20px;
  }
</style>

<script>
window.addEventListener('block-loaded-list2', () => {
    console.log('Block loaded');
});

const showLoadingScreen = () => {
    document.getElementById('loading-screen').style.display = 'block';
};

const hideLoadingScreen = () => {
    document.getElementById('loading-screen').style.display = 'none';
};

const dispatchReloadBlockListDetailsEvent = () => {
    window.dispatchEvent(new CustomEvent('reload-block-list-details1'));
};

let observer;
let reloadInterval;

window.addEventListener('submit-form-success-form1', () => {
    showLoadingScreen();

    const targetElements = document.querySelectorAll('#list2 h3');

    const config = { childList: true };

    const callback = function (mutationsList, observer) {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList') {
                console.log('Child elements have changed');
                hideLoadingScreen();
                dispatchReloadBlockListDetailsEvent();

                clearInterval(reloadInterval);

                observer.disconnect();
            }
        }
    };

    targetElements.forEach(targetElement => {
        observer = new MutationObserver(callback);
        observer.observe(targetElement, config);
    });

    reloadInterval = setInterval(() => {
        window.dispatchEvent(new CustomEvent('reload-block-list2'));
    }, 4000);
});

const onRecords = (e) => {
    console.log(e.detail);
};

</script>

How to adapt the script to your use case?

  • You can customize the waiting screen as you wish, obviously.
  • update submit-form-success-form1 by changing form1 to the ID:Name of your form block.
  • Same for reload-block-list2 and reload-block-list-details1
  • You will absolutely need to adapt this line: const targetElements = document.querySelectorAll('#list2 h3');

#list2 h3 is the selector checked by the mutation observer (targetElement)
How did I get this precise selector? It’s simple: open the dev tool/inspector of your browser and point to the element that should change when the data is finally updated. In my use case I chose the text element for the title of the list block items (Project A, Project B, Project C, etc.).
Once you selected it in your dev tool, just check what is the type of the selector. Here in my use case it’s a h3. You don’t need to use the class (unless you need your mutation observer to point to a more precise selector).

I insert a screenshot of my dev tool (in french but you will get it) below.

Screenshot of my browser dev tool:

1 Like

Another version of the code if you want to redirect the user to another page instead of staying on the same page.

Don’t forget to change =>

  1. This line: window.location.href = '/hide-show-tabs'; /hide-show-tabs to be replaced by /xxxx (the page url slug you want the user to be redirected to)
  2. #list2 h3 from const targetElements = document.querySelectorAll('#list2 h3');
  3. form1 from window.addEventListener('submit-form-success-form1', () => {
  4. list2 from window.addEventListener('block-loaded-list2', () => {
  5. list2 from window.dispatchEvent(new CustomEvent('reload-block-list2'));
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">

<div id="loading-screen">
  <div class="loading-content">
    <p>Your xxxxx is being created. Patience...</p>
    <i class="fas fa-spinner fa-spin loading-spinner"></i>
  </div>
</div>

<style>
  #loading-screen {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #4893eb;
    z-index: 9999;
  }

  #loading-screen .loading-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    text-align: center;
    font-size: 20px;
    font-weight: bold;
  }

  #loading-screen .loading-spinner {
    font-size: 40px;
    margin-top: 20px;
  }
</style>

<script>
window.addEventListener('block-loaded-list2', () => {
    console.log('Block loaded');
});

const showLoadingScreen = () => {
    document.getElementById('loading-screen').style.display = 'block';
};

const hideLoadingScreen = () => {
    document.getElementById('loading-screen').style.display = 'none';
};

const redirectToPage = () => {
    window.location.href = '/hide-show-tabs';
};

window.addEventListener('submit-form-success-form1', () => {
    showLoadingScreen();

    const targetElements = document.querySelectorAll('#list2 h3');

    const config = { childList: true };

    const callback = function (mutationsList, observer) {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList') {
                console.log('Child elements have changed');
                hideLoadingScreen();
                redirectToPage();
            }
        }
    };

    targetElements.forEach(targetElement => {
        const observer = new MutationObserver(callback);
        observer.observe(targetElement, config);
    });

    const reloadInterval = setInterval(() => {
        window.dispatchEvent(new CustomEvent('reload-block-list2'));
    }, 4000);
});

const onRecords = (e) => {
    console.log(e.detail);
};

</script>
2 Likes

Hi Matthieu,

I have seen different posts from you where you provide custom code for different waiting screens. From the responses to these posts I understand that your code should work, but somehow I only manage to successfully implement the reload triggers with time delay. But no matter what I try, I can’t get the waiting screen to show up… do you have any idea what may be the cause of the waiting screen not showing up?

Note that I already tried with the browser’s popup blocker disabled. Also, I did manage to do something else: I had already copied the code for a generic loading screen into the website’s general custom code (if I’m not mistaken you also provided that code). And when I call upon that screen (instead of the code in this post for example), it DOES show up (but without any text specific to the trigger on why the screen is showing, plus the spinner is suddenly presented on top-left, while the custom code says center/center).

Best regards,
Thijs

Hi,

Just copy pasting the code won’t work.

For example, this line => const targetElements = document.querySelectorAll('#list2 h3');

This line needs to be udpated according to your use case, as I wrote above. The script relies on a mutation observer, the target element for your use case might not be the same.

If this is another problem, it can come from … anywhere :woozy_face: (but not from browser’s popup blocker as the code is not related to popups).

Hi Matthieu,

Yes I understand the triggers to (de)activate the loading screen have to be tailored. And I succeeded in the one that has a fixed time-out. My problem is that despite the code saying it should activate… it doesn’t show (but it simply reloads the blocks as specified in the code).

Thanks for you response!

All codes work properly, that’s all I can say.

I can debug if you show me your complete code (the dynamic timeout one, the one I wrote in this page). and if you explain the complete workflow of your page (with block IDs too).

Hi,

I updated the codes for a better understanding

  • Easier selector to find
  • More dynamic (added .forEach)