Success at Last!

#5
by awacke1 - opened
Owner
β€’
edited Oct 14

I have finally completed a working full Azure and Microsoft MS Graph API implementation which can use all the interesting MS AI features in M365 products to manage CRUD patterns for the graph features across products.

This app shows initial implementation of security, authentication, scopes, and access to Outlook, Calendar, Tasks, Onedrive and other apps for CRUD pattern as AI agent service skills to integrate with your AI workflow.

Below are initial screens showing integration:

URL: https://huggingface.co/spaces/awacke1/MSGraphAPI
Discussion: https://huggingface.co/spaces/awacke1/MSGraphAPI/discussions/5

Best of AI on
@Azure
and
@Microsoft
on
@HuggingFace
:
https://huggingface.co/microsoft
https://microsoft.com/en-us/research/

image.png

image.png

image.png

Spare Parts

    
    # πŸ“ M365 Products with MS Graph Integration & AI Features
    st.sidebar.title("πŸ“ M365 Products")
    st.sidebar.write("Toggle integration for each product:")
    
    # πŸŽ›οΈ Product Integration Toggles
    products = {
        "πŸ“§ Outlook": {
            "ai_capabilities": "Copilot for enhanced email writing, calendar management, and scheduling.",
            "graph_api": "Access to mail, calendar, contacts, and events."
        },
        "πŸ“’ OneNote": {
            "ai_capabilities": "Content suggestion, note organization, and OCR for extracting text from images.",
            "graph_api": "Manage notebooks, sections, and pages."
        },
        "πŸ“Š Excel": {
            "ai_capabilities": "Copilot for advanced data analysis, data insights, and formula generation.",
            "graph_api": "Create and manage worksheets, tables, charts, and workbooks."
        },
        "πŸ“„ Word": {
            "ai_capabilities": "Copilot for document drafting, summarization, and grammar improvements.",
            "graph_api": "Document content access, templates, and file management."
        },
        "πŸ—ƒοΈ SharePoint": {
            "ai_capabilities": "Intelligent search, document tagging, and metadata extraction.",
            "graph_api": "Access to sites, lists, files, and document libraries."
        },
        "πŸ“… Teams": {
            "ai_capabilities": "Copilot for meeting summaries, transcription, and chat suggestions.",
            "graph_api": "Manage chats, teams, channels, and meetings."
        },
        "πŸ’¬ Viva": {
            "ai_capabilities": "Personalized learning insights, well-being insights, and productivity suggestions.",
            "graph_api": "Access to user analytics and learning modules."
        },
        "πŸš€ Power Platform": {
            "ai_capabilities": "Automation with AI Builder, data insights, and custom AI models.",
            "graph_api": "Automation workflows, app creation, and data visualization."
        },
        "🧠 Copilot": {
            "ai_capabilities": "Embedded across Word, Excel, Outlook, Teams, and more for AI-driven productivity.",
            "graph_api": "Underpins Copilot's access to data and integrations."
        },
        "πŸ—‚οΈ OneDrive": {
            "ai_capabilities": "Intelligent file organization and search.",
            "graph_api": "File and folder access, sharing, and metadata."
        },
        "πŸ’‘ PowerPoint": {
            "ai_capabilities": "Design suggestions, presentation summarization, and speaker coaching.",
            "graph_api": "Presentation creation, slide management, and templates."
        },
        "πŸ“š Microsoft Bookings": {
            "ai_capabilities": "Automated scheduling and reminders.",
            "graph_api": "Booking calendars, services, and appointment details."
        },
        "πŸ““ Loop": {
            "ai_capabilities": "Real-time collaboration and content suggestions.",
            "graph_api": "Access to shared workspaces and collaborative pages."
        },
        "πŸ—£οΈ Translator": {
            "ai_capabilities": "Real-time language translation and text-to-speech.",
            "graph_api": "Integrated into communication and translation services."
        },
        "πŸ“‹ To Do & Planner": {
            "ai_capabilities": "Task prioritization and smart reminders.",
            "graph_api": "Task creation, management, and synchronization."
        },
        "πŸ”— Azure OpenAI Service": {
            "ai_capabilities": "Access to GPT models for custom AI implementations.",
            "graph_api": "Used indirectly for building custom AI models into workflows."
        }
    }
    
    # πŸ—³οΈ Create toggles for each product
    selected_products = {}
    for product, info in products.items():
        selected = st.sidebar.checkbox(product)
        if selected:
            st.sidebar.write(f"**AI Capabilities:** {info['ai_capabilities']}")
            st.sidebar.write(f"**Graph API:** {info['graph_api']}")
            selected_products[product] = True
    
    # πŸš€ Sidebar navigation
    st.sidebar.title("Navigation")
    menu = st.sidebar.radio("Go to", [
        "1️⃣ Dashboard",
        "🏠 Landing Page",
        "πŸ“… Upcoming Events",
        "πŸ“† Schedule",
        "πŸ“ Agenda",
        "πŸ” Event Details",
        "βž• Add Event",
        "πŸ”Ž Filter By"
    ])
# Define product to scope mapping
PRODUCT_SCOPES = {
    "πŸ“§ Outlook": ['Mail.Read', 'Mail.Send', 'Calendars.ReadWrite'],
    "πŸ“’ OneNote": ['Notes.Read', 'Notes.Create'],
    "πŸ“Š Excel": ['Files.ReadWrite.All'],
    "πŸ“„ Word": ['Files.ReadWrite.All'],
    "πŸ—ƒοΈ SharePoint": ['Sites.Read.All', 'Sites.ReadWrite.All'],
    "πŸ“… Teams": ['Team.ReadBasic.All', 'Channel.ReadBasic.All'],
    "πŸ’¬ Viva": ['Analytics.Read'],
    "πŸš€ Power Platform": ['Flow.Read.All'],
    "🧠 Copilot": ['Cognitive.Read'],
    "πŸ—‚οΈ OneDrive": ['Files.ReadWrite.All'],
    "πŸ’‘ PowerPoint": ['Files.ReadWrite.All'],
    "πŸ“š Microsoft Bookings": ['Bookings.Read.All', 'Bookings.ReadWrite.All'],
    "πŸ““ Loop": ['Files.ReadWrite.All'],
    "πŸ—£οΈ Translator": ['Translation.Read'],
    "πŸ“‹ To Do & Planner": ['Tasks.ReadWrite'],
    "πŸ”— Azure OpenAI Service": ['AzureAIServices.ReadWrite.All']
}
import os
import streamlit as st
import requests
import msal
from datetime import datetime, timedelta
import calendar

# Configuration
APPLICATION_ID_KEY = os.getenv('APPLICATION_ID_KEY')
CLIENT_SECRET_KEY = os.getenv('CLIENT_SECRET_KEY')
AUTHORITY_URL = 'https://login.microsoftonline.com/common'
REDIRECT_URI = 'https://huggingface.co/spaces/awacke1/MSGraphAPI'

# Define product to scope mapping and links
PRODUCT_SCOPES = {
    "πŸ“§ Outlook": {'scopes': ['Mail.Read', 'Mail.Send'], 'link': 'https://outlook.office.com/mail/'},
    "πŸ“… Calendar": {'scopes': ['Calendars.ReadWrite'], 'link': 'https://outlook.office.com/calendar/'},
    "πŸ“‹ Tasks": {'scopes': ['Tasks.ReadWrite'], 'link': 'https://to-do.office.com/tasks/'},
    "πŸ—‚οΈ OneDrive": {'scopes': ['Files.ReadWrite.All'], 'link': 'https://onedrive.live.com/'},
    # ... (other products)
}

BASE_SCOPES = ['User.Read']

def get_msal_app():
    return msal.ConfidentialClientApplication(
        client_id=APPLICATION_ID_KEY,
        client_credential=CLIENT_SECRET_KEY,
        authority=AUTHORITY_URL
    )

def get_access_token(code):
    client_instance = get_msal_app()
    try:
        result = client_instance.acquire_token_by_authorization_code(
            code=code,
            scopes=st.session_state.get('request_scopes', BASE_SCOPES),
            redirect_uri=REDIRECT_URI
        )
        if 'access_token' in result:
            return result['access_token']
        else:
            raise Exception(f"Error acquiring token: {result.get('error_description')}")
    except Exception as e:
        st.error(f"Exception in get_access_token: {str(e)}")
        raise

def make_api_call(access_token, endpoint, method='GET', data=None):
    headers = {'Authorization': f'Bearer {access_token}', 'Content-Type': 'application/json'}
    url = f'https://graph.microsoft.com/v1.0/{endpoint}'
    
    if method == 'GET':
        response = requests.get(url, headers=headers)
    elif method == 'POST':
        response = requests.post(url, headers=headers, json=data)
    else:
        raise ValueError(f"Unsupported method: {method}")
    
    if response.status_code in [200, 201]:
        return response.json()
    else:
        st.error(f"API call failed: {response.status_code} - {response.text}")
        return None

def handle_outlook_integration(access_token):
    st.subheader("πŸ“§ Outlook Integration")
    st.markdown(f"[Open Outlook]({PRODUCT_SCOPES['πŸ“§ Outlook']['link']})")
    
    emails = make_api_call(access_token, 'me/messages?$top=10&$orderby=receivedDateTime desc')
    if emails and 'value' in emails:
        for email in emails['value']:
            with st.expander(f"From: {email['from']['emailAddress']['name']} - Subject: {email['subject']}"):
                st.write(f"Received: {email['receivedDateTime']}")
                st.write(f"Body: {email['bodyPreview']}")
    else:
        st.write("No emails found or unable to fetch emails.")

def handle_calendar_integration(access_token):
    st.subheader("πŸ“… Calendar Integration")
    st.markdown(f"[Open Calendar]({PRODUCT_SCOPES['πŸ“… Calendar']['link']})")
    
    # Get the current month's start and end dates
    now = datetime.now()
    start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    end_of_month = start_of_month.replace(month=start_of_month.month % 12 + 1, day=1) - timedelta(days=1)
    
    events = make_api_call(access_token, f"me/calendarView?startDateTime={start_of_month.isoformat()}&endDateTime={end_of_month.isoformat()}&$orderby=start/dateTime")
    
    if events and 'value' in events:
        # Create a calendar view
        cal = calendar.monthcalendar(now.year, now.month)
        st.write(f"Calendar for {now.strftime('%B %Y')}")
        
        # Create a placeholder for each day
        day_placeholders = {}
        for week in cal:
            cols = st.columns(7)
            for i, day in enumerate(week):
                if day != 0:
                    day_placeholders[day] = cols[i].empty()
                    day_placeholders[day].write(f"**{day}**")
        
        # Populate the calendar with events
        for event in events['value']:
            start_date = datetime.fromisoformat(event['start']['dateTime'][:-1])  # Remove 'Z' from the end
            day = start_date.day
            if day in day_placeholders:
                day_placeholders[day].write(f"{start_date.strftime('%H:%M')} - {event['subject']}")
    else:
        st.write("No events found or unable to fetch events.")
    
    st.write("Add a new event:")
    event_subject = st.text_input("Event Subject")
    event_date = st.date_input("Event Date")
    event_time = st.time_input("Event Time")
    if st.button("Add Event"):
        event_start = datetime.combine(event_date, event_time)
        event_end = event_start + timedelta(hours=1)
        new_event = {
            "subject": event_subject,
            "start": {
                "dateTime": event_start.isoformat(),
                "timeZone": "UTC"
            },
            "end": {
                "dateTime": event_end.isoformat(),
                "timeZone": "UTC"
            }
        }
        result = make_api_call(access_token, 'me/events', method='POST', data=new_event)
        if result:
            st.success("Event added successfully!")
        else:
            st.error("Failed to add event.")

def handle_tasks_integration(access_token):
    st.subheader("πŸ“‹ Tasks Integration")
    st.markdown(f"[Open Tasks]({PRODUCT_SCOPES['πŸ“‹ Tasks']['link']})")
    
    tasks = make_api_call(access_token, 'me/todo/lists')
    if tasks and 'value' in tasks:
        default_list = next((list for list in tasks['value'] if list['wellknownListName'] == 'defaultList'), None)
        if default_list:
            tasks = make_api_call(access_token, f"me/todo/lists/{default_list['id']}/tasks")
            if tasks and 'value' in tasks:
                for task in tasks['value']:
                    st.write(f"Task: {task['title']}")
                    st.write(f"Status: {'Completed' if task['status'] == 'completed' else 'Not Completed'}")
                    st.write("---")
            else:
                st.write("No tasks found or unable to fetch tasks.")
        else:
            st.write("Default task list not found.")
    else:
        st.write("Unable to fetch task lists.")
    
    st.write("Add a new task:")
    task_title = st.text_input("Task Title")
    if st.button("Add Task"):
        new_task = {
            "title": task_title
        }
        result = make_api_call(access_token, f"me/todo/lists/{default_list['id']}/tasks", method='POST', data=new_task)
        if result:
            st.success("Task added successfully!")
        else:
            st.error("Failed to add task.")

def handle_onedrive_integration(access_token):
    st.subheader("πŸ—‚οΈ OneDrive Integration")
    st.markdown(f"[Open OneDrive]({PRODUCT_SCOPES['πŸ—‚οΈ OneDrive']['link']})")
    
    files = make_api_call(access_token, 'me/drive/root/children')
    if files and 'value' in files:
        for file in files['value']:
            st.write(f"Name: {file['name']}")
            st.write(f"Type: {'Folder' if 'folder' in file else 'File'}")
            st.write(f"Last Modified: {file['lastModifiedDateTime']}")
            st.write("---")
    else:
        st.write("No files found or unable to fetch files.")

def main():
    st.title("πŸ¦„ MS Graph API with AI & Cloud Integration for M365")

    st.sidebar.title("πŸ“ M365 Products")
    st.sidebar.write("Select products to integrate:")
    
    selected_products = {}
    for product in PRODUCT_SCOPES.keys():
        selected = st.sidebar.checkbox(product)
        if selected:
            selected_products[product] = True

    request_scopes = BASE_SCOPES.copy()
    for product in selected_products:
        request_scopes.extend(PRODUCT_SCOPES[product]['scopes'])
    request_scopes = list(set(request_scopes))
    
    st.session_state['request_scopes'] = request_scopes

    if 'access_token' not in st.session_state:
        client_instance = get_msal_app()
        auth_url = client_instance.get_authorization_request_url(
            scopes=request_scopes,
            redirect_uri=REDIRECT_URI
        )
        st.write('πŸ‘‹ Please [click here]({}) to log in and authorize the app.'.format(auth_url))
        
        query_params = st.query_params
        if 'code' in query_params:
            code = query_params.get('code')
            st.write('πŸ”‘ Authorization Code Obtained:', code[:10] + '...')
            
            try:
                access_token = get_access_token(code)
                st.session_state['access_token'] = access_token
                st.success("Access token acquired successfully!")
                st.rerun()
            except Exception as e:
                st.error(f"Error acquiring access token: {str(e)}")
                st.stop()
    else:
        access_token = st.session_state['access_token']
        
        user_info = make_api_call(access_token, 'me')
        if user_info:
            st.sidebar.write(f"πŸ‘‹ Hello, {user_info.get('displayName', 'User')}!")
        
        if selected_products:
            for product in selected_products:
                if product == "πŸ“§ Outlook":
                    handle_outlook_integration(access_token)
                elif product == "πŸ“… Calendar":
                    handle_calendar_integration(access_token)
                elif product == "πŸ“‹ Tasks":
                    handle_tasks_integration(access_token)
                elif product == "πŸ—‚οΈ OneDrive":
                    handle_onedrive_integration(access_token)
                # Add more product integrations here
        else:
            st.write("No products selected. Please select products from the sidebar.")

if __name__ == "__main__":
    main()

My goal is to find a business solution that not only helps streamline project managementβ€”although that’s the primary aimβ€”but also makes overall business operations more cohesive. I want to avoid spending excessive time ensuring information flows smoothly between departments and instead ensure all specialists work together seamlessly. In short, I’m looking for something that optimizes processes and eliminates unnecessary steps.

What about ERP? In my opinion, it’s an optimal solution for businesses of any size, whether it’s a small business or a startup. The key factor is the company’s readiness to implement a new system. Currently, I’m actively working with IFS Cloud, and my choice is partly influenced by a partnership with Novacura https://www.novacura.com/ifs-services-ams-2/ , which offers a full range of services aimed at optimizing and customizing IFS Cloud to fit business needs. Not only is the cloud system itself effective, but the availability of specialists to assist when needed adds a lot of value.

Sign up or log in to comment