To Do List help when no due date

I’ve got a to do list, that I use to notify me of upcoming chores. I’ve used a few examples from elsewhere on this forum to make it work, but there’s something I can’t work out - when a task doesn’t have a due date, none of the sensors work.

Here is my config:

template:
  - trigger:
      - trigger: time_pattern
        minutes: /1
      - platform: state
        entity_id: todo.chores
    action:
      - service: todo.get_items
        data:
          status: needs_action
        target:
          entity_id: todo.chores
        response_variable: todo_list
    sensor:
      - name: "To Do List - Today"
        unique_id: todo_list_today
        state: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if task['due'].split('T')[0] == today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            {{ ns.result | count }}  
        attributes:
          items: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if task['due'].split('T')[0] == today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            
            {%- if ns.result is iterable -%}
            {%- for item in ns.result %}  
            - {{ item }}
            
            {%- endfor -%}
            {%- endif -%}

This works fine as long as all tasks have a due date. When one doesn’t, it comes back as unavailable.

My questions are:

  • How can I make the above work when there is not due date?
  • Can I create a new sensor that only brings back the items where there is no due date?

Thanks in advance!

When there is no due date, the code task['due'] will return null, so then calling split on it will cause an error - which is why you’re getting unavailable.

A simple way to avoid the error would be to provide a default value:

{%- if (task['due'] | default('')).split('T')[0] == today -%}

This would skip that task - if you wanted to include it instead you could just use default(today).

However, you don’t need to do this with a loop as selectattr will find the ones you want and ignore if missing:

{%- set today = now().strftime('%Y-%m-%d')-%}
{{ todo_list['todo.chores']['items']
  | selectattr('due', 'eq', today)
  | list | count
}}

Actually the above will only work if you use due date not date/time. In that case you’d have to use selectattr('due', 'match', today + '*').

Thanks for this!

I used the first piece of code as that also worked with other sensors I had. They look for overdue and upcoming tasks.

I don’t get the error now, but the tasks that don’t have a due date are now appearing in the list of overdue tasks. Do you know why this is?


      - name: "To Do List - Overdue"
        unique_id: todo_list_overdue
        state: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if (task['due'] | default('')).split('T')[0] < today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            {{ ns.result | count }}  
        attributes:
          items: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if (task['due'] | default('')).split('T')[0] < today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            
            {%- if ns.result is iterable -%}
            {%- for item in ns.result %}  
            - {{ item }}
            
            {%- endfor -%}
            {%- endif -%}

Fixed it! Sharing my configuration below for anyone else that needs it:

template:
  - trigger:
      - trigger: time_pattern
        minutes: /1
      - platform: state
        entity_id: todo.chores
    action:
      - service: todo.get_items
        data:
          status: needs_action
        target:
          entity_id: todo.chores
        response_variable: todo_list

Items due today:

    sensor:
      - name: "To Do List - Today"
        unique_id: todo_list_today
        state: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if (task['due'] | default('')).split('T')[0] == today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            {{ ns.result | count }}  
        attributes:
          items: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if (task['due'] | default('')).split('T')[0] == today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            
            {%- if ns.result is iterable -%}
            {%- for item in ns.result %}  
            - {{ item }}
            
            {%- endfor -%}
            {%- endif -%}   

No due date:

   - name: "To Do List - No Due Date"
        unique_id: todo_list_no_due_date
        state: >
            {%- set ns =  namespace(result = []) -%}
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if task['due'] == null -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            {{ ns.result | count }}  
        attributes:
          items: >            
            {%- set ns =  namespace(result = []) -%}
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if task['due'] == null -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            {%- if ns.result is iterable -%}
            {%- for item in ns.result %}  
            - {{ item }}
            
            {%- endfor -%}
            {%- endif -%}     

Overdue:

      - name: "To Do List - Overdue"
        unique_id: todo_list_overdue
        state: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if (task['due'] | default(today)).split('T')[0] < today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            {{ ns.result | count }}  
        attributes:
          items: >
            {%- set today = now().strftime('%Y-%m-%d')-%}
            {%- set ns =  namespace(result = []) -%}
            
            {% set tasks_list = todo_list['todo.chores']['items'] %}
            {%- for task in tasks_list -%}
            {%- if (task['due'] | default(today)).split('T')[0] < today -%}
            {%- set ns.result = ns.result + [task['summary']] -%}
            {%- endif -%}
            {%- endfor -%}            
            
            {%- if ns.result is iterable -%}
            {%- for item in ns.result %}  
            - {{ item }}
            
            {%- endfor -%}
            {%- endif -%}