Делаем ознакомление с элементом списка SharePoint 2010

в 23:51, , рубрики: Без рубрики

Принцип работы ознакомления довольно прост. Пользователь при просмотре элемента списка видит кнопку Прочитал после нажатия на которую данные о нем и времени нажатия попадают в другой список где будут хранится. Этот список будет автоматически создаваться после того как веб парта будет размещена на странице просмотра элемента, а имя его будет формироваться так ReadList_<Guid списка для ознакомления>. Для просмотра списков ознакомленных и не ознакомленных мы напишем еще одну веб парту которую разместим на форме редактирования списка который будем читать, так как подразумевается что обычные пользователи могут просматривать, но не редактировать документ.

Вот как выглядит веб парта ознакомление.
До нажатия на кнопку:
image

И после нажатия:
image
Создаем собственно сам список, с элементами которого пользователи должны ознакомиться. Я назвал его TestReadList, добавляем дополнительное поле Assigned to тип поля Person or Group смысл этого поля станет ясен когда будем создавать веб парту для просмотра ознакомленных.
В Visual Studio создаем пустой проект SharePoint2010 SPConfirmReadProject.
Добавляем в проект Visual Web Part назовем её ConfirmWebPart, так же добавим к проекту ссылку на папку Images SharePoint’a (Правой кнопкой на проекте. Add->SharePoint “Images” Mapped Folder) после этого добавьте к папку ImagesSPConfirmReadProject свой рисунок кнопки. Он будет использоваться в LinkButton.
Вот код ConfirmWebPart.ascx

<table>
    <tr>
        <td>
            <asp:LinkButton ID="bRead" runat="server" OnClick="bRead_Click"><img src="../_Layouts/Images/SPConfirmReadProject/accept.png" style="border:0px;"/>Прочитал</asp:LinkButton>
        </td>
    </tr>
    <tr>
        <td>
            <asp:Label ID="lStatus" runat="server" Text=""></asp:Label>
        </td>
    </tr>
</table>

Тут собственно создаём LinkButton и Label.

Переходим к коду ConfirmWebPart.asxc.cs:

protected void Page_Load(object sender, EventArgs e)
        {
            bool isReal = false;
            //Проверяем сеществует ли список для записи данных о прочтении.
            foreach (SPList list in SPContext.Current.Web.Lists)
            {
                if (list.Title == "ReadList_" + SPContext.Current.ListId)
                {
                    isReal = true;
                }
            }
            SPList listConfirmReadUser;
            //Если сеществует то обращаемся к нему
            if (isReal)
                listConfirmReadUser = SPContext.Current.Web.Lists["ReadList_"+SPContext.Current.ListId];
            //Если нет то создаем его
            else
            {
                SPContext.Current.Web.Lists.Add("ReadList_" + SPContext.Current.ListId, "", SPListTemplateType.GenericList);
                listConfirmReadUser = SPContext.Current.Site.RootWeb.Lists["ReadList_" + SPContext.Current.ListId];
                listConfirmReadUser.Fields.Add("User", SPFieldType.User, true);
                listConfirmReadUser.Fields.Add("Date", SPFieldType.DateTime, true);
                listConfirmReadUser.Fields.AddLookup("ListItem", SPContext.Current.ListId, true);
                listConfirmReadUser.Update();
            }
            //И собственно ищем текущего пользователя и текущий элемент списка
            SPListItemCollection listItems = listConfirmReadUser.Items;
            foreach (SPListItem item in listItems)
            {
                string user = item["User"].ToString().Split('#')[1];
                string listItem = item["ListItem"].ToString().Split('#')[0];
                if ((listItem.Remove(listItem.Length-1) == SPContext.Current.ItemId.ToString())
                    && (user.ToString() == SPContext.Current.Web.CurrentUser.Name.ToString()))
                {
                    //если находим то прячем кнопку остовляем только текст с временем ознакомления.
                    bRead.Visible = false;
                    lStatus.Text = "Вы ознакомлены с документом " + item["Date"].ToString();
                }
            }
        }

        //А вот так записываем данные пользователя при нажатии на кнопку
        protected void ConfirmUser()
        {
            var listConfirmReadUser = SPContext.Current.Site.RootWeb.Lists["ReadList_" + SPContext.Current.ListId];
            SPListItemCollection listItems = listConfirmReadUser.Items;

            SPListItem item = listItems.Add();
            item["Date"] = DateTime.Now;
            item["ListItem"] = SPContext.Current.ItemId;
            item["User"] = SPContext.Current.Web.CurrentUser;
            item["Title"] = "Ознакомлен: " + SPContext.Current.Web.CurrentUser.ToString() + " - " + DateTime.Now;
            item.Update();

            bRead.Visible = false;
            lStatus.Text = "Вы ознакомлены с документом " + item["Date"].ToString();
        }

        protected void bRead_Click(object sender, EventArgs e)
        {
            ConfirmUser();
        }

Всё теперь можно деплоить. Веб парта размещается на форме просмотра элемента.
Для этого на вкладке ленты List выберите Form Web Parts -> Default Display Form как показано на рисунке.
image
В окне формы нажмите Add a Web Part. В Categories выберем Custom, а в Web Parts нашу веб парту у меня она называется SPConfirmReadProject — ReadUsersWebPart. Жмём кнопку Add и Stop Editing.

Вот собственно и все по веб парте ознакомление.

Теперь напишем веб парту просмотра кто ознакомился, а кто нет.
Веб парта состоит из 2 LinkButton, Label и GridView.
Вот как это выглядит при нажатии на кнопку «С документом ознакомлены».
image
Тут все просто мы тупо лезем в список ознакомленных и вытаскиваем их. А интересное происходит если мы нажмем на кнопку «Не ознакомлены».
image
Для этого используется поле «Assigned to» в котором перечислены люди иили группы которым назначено читать элемент. Для решения этой задачи мы берем список людей из поля «Assigned to» и сопоставляем его с людьми из списка прочитавших. Приступим.

Добавим VisualWebPart в проект. Назовем её ReadUsersWebPart.
Добавим в ReadUsersWebPart.ascx

<table>
    <tr>
        <td>
            <asp:LinkButton ID="lbRead" runat="server" OnClick="lbRead_Click" BorderWidth="0"><img src="../_Layouts/Images/SPConfirmReadProject/thumb_up.png" style="border:0px;"  />С документом ознакомлены</asp:LinkButton>
        </td>
        <td>
            <p>
            </p>
        </td>
        <td>
            <asp:LinkButton ID="lbUnRead" runat="server" OnClick="lbUnRead_Click" BorderWidth="0"><img src="../_Layouts/Images/SPConfirmReadProject/thumb_down.png" style="border:0px;"  />Не ознакомлены</asp:LinkButton>
        </td>
    </tr>
</table>
<p></p>
<asp:Label ID="Label1" runat="server"></asp:Label>
<asp:GridView ID="gridView" runat="server" AllowPaging="True" BackColor="White"
    BorderColor="#CCCCCC" BorderStyle="None" BorderWidth="1px" CellPadding="4" EnableModelValidation="True"
    ForeColor="Black" GridLines="Horizontal"
    PageSize="20">
    <FooterStyle BackColor="#CCCC99" ForeColor="Black" />
    <HeaderStyle BackColor="#333333" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="White" ForeColor="Black" HorizontalAlign="Right" />
    <SelectedRowStyle BackColor="#CC3333" Font-Bold="True" ForeColor="White" />
</asp:GridView>

А в ReadUsersWebPart.ascx.cs запишем следующее:

private SPGroup SearchGroup(string group)
        {
            SPGroup groupObject = null;
            foreach (SPGroup singleGroup in SPContext.Current.Web.Groups)
            {
                if (group == singleGroup.Name)
                {
                    groupObject = singleGroup;
                }
            }
            return groupObject;
        }
//Формируем таблицу читавших
protected void ReadUsers()
{
            var table = new DataTable("ReadList");
            var colFIO = new DataColumn();
            colFIO.DataType = System.Type.GetType("System.String");
            colFIO.ColumnName = "Сотрудник";
            table.Columns.Add(colFIO);

            var colDate = new DataColumn();
            colDate.DataType = System.Type.GetType("System.DateTime");
            colDate.ColumnName = "Прочитал";
            table.Columns.Add(colDate);

            string idItem = SPContext.Current.ItemId.ToString();
            string idUser = SPContext.Current.Web.CurrentUser.ID.ToString().Split('#')[0].ToString().Replace(";","");

            var listConfirmReadUser = SPContext.Current.Web.Lists["ReadList_" + SPContext.Current.ListId];
            var query = new SPQuery();

            string calmQuery = "<Where><And><Eq><FieldRef Name='ListItem' LookupId='true'/><Value Type='Lookup'>" + idItem +
                               "</Value></Eq><Eq><FieldRef Name='User' LookupId='true'/><Value Type='User'>" + idUser +
                               "</Value></Eq></And></Where>";
            query.Query = calmQuery;

            SPListItemCollection listItems = listConfirmReadUser.GetItems(query);
            if (listItems.Count > 0)
                foreach (SPListItem item in listItems)
                {
                    DataRow row;
                    row = table.NewRow();
                    row["Сотрудник"] = item["User"].ToString().Split('#')[1];
                    row["Прочитал"] = item["Date"];
                    table.Rows.Add(row);
                }

            Label1.Text = "";

            gridView.DataSource = table;
            gridView.DataBind();
            if (table.Rows.Count < 1)
            {
                Label1.Text = "Никто не читал документ.";
            }
        }

        //Формируем таблицу не читавших
protected void UnReadUsers()
{
            string idItem = SPContext.Current.ItemId.ToString();
            string idUser = SPContext.Current.Web.CurrentUser.ID.ToString().Split('#')[0].ToString().Replace(";", "");
            string currentValue = string.Empty;
            string FieldName = string.Empty;
            try
            {
                currentValue = SPContext.Current.Item["Кому назначено"].ToString();
                FieldName = "Кому назначено";
            }
            catch
            {
                currentValue = SPContext.Current.Item["Assigned to"].ToString();
                FieldName = "Assigned to";
            }
            List<SPUser> listAllUser = new List<SPUser>();
            SPFieldUser UsersColumn = (SPFieldUser)SPContext.Current.Fields.GetField(FieldName);
            SPFieldUserValueCollection Users = (SPFieldUserValueCollection)UsersColumn.GetFieldValue(SPContext.Current.Item[FieldName].ToString());
            foreach (SPFieldUserValue user in Users)
            {
                SPGroup group = SearchGroup(user.LookupValue);
                if (group != null)
                {
                    SPUserCollection groupUsers = group.Users;
                    foreach (SPUser groupUser in groupUsers)
                    {
                        if (groupUser != null)
                            listAllUser.Add(groupUser);
                    }
                }
                else
                {
                    if (user.User != null)
                        listAllUser.Add(user.User);
                }
            }

            var query = new SPQuery();
            string calmQuery = "<Where><And><Eq><FieldRef Name='ListItem' LookupId='true'/><Value Type='Lookup'>" + idItem +
                               "</Value></Eq><Eq><FieldRef Name='User' LookupId='true'/><Value Type='User'>" + idUser +
                               "</Value></Eq></And></Where>";
            query.Query = calmQuery;
            SPList list = SPContext.Current.Web.Lists["ReadList_" + SPContext.Current.ListId];
            SPListItemCollection listReadUsers = list.GetItems(query);

            if (listReadUsers.Count > 0)
            {
                List<SPUser> listReadUser = new List<SPUser>();
                foreach (SPListItem item in listReadUsers)
                {
                    SPFieldUser UserReadColumn = (SPFieldUser)item.Fields.GetField("User");
                    SPFieldUserValue ur = (SPFieldUserValue)UserReadColumn.GetFieldValue(item["User"].ToString());
                    listReadUser.Add(ur.User);
                }

                if (listReadUser.Count() > 0)
                    foreach (SPUser rUser in listReadUser)
                    {
                        if (rUser != null)
                            listAllUser.RemoveAll(u => u.ID == rUser.ID);
                    }
            }
            List<SPUser> usd = new List<SPUser>();

            foreach (SPUser spUser in listAllUser)
            {
                List<SPUser> listUsr = (from u in listAllUser
                                        where (u.ID == spUser.ID)
                                        select u).ToList();
                if (listUsr.Count() > 1)
                {
                    usd.Add(listUsr[0]);
                }
            }

            foreach (SPUser spUser in usd)
            {
                listAllUser.Remove(spUser);
            }

            var table = new DataTable("UnReadList");
            var colFIO = new DataColumn();
            colFIO.DataType = System.Type.GetType("System.String");
            colFIO.ColumnName = "Сотрудник";
            table.Columns.Add(colFIO);
            foreach (SPUser spUser in listAllUser)
            {
                DataRow row;
                row = table.NewRow();
                row["Сотрудник"] = spUser.Name;
                table.Rows.Add(row);
            }

            Label1.Text = "";

            gridView.DataSource = table;
            gridView.DataBind();

            if (listAllUser.Count() < 1)
            {
                Label1.Text = "Документ прочтен всеми сотрудниками.";
            }
        }
        
protected void lbRead_Click(object sender, EventArgs e)
        {
            ReadUsers();
        }

protected void lbUnRead_Click(object sender, EventArgs e)
        {
            UnReadUsers();
        }

Далее можно сделать рассылку пользователям которые прописаны в поле Assigned to с помощью Workflow в Visual Studio или SharePoint Designer.

Надеюсь статья окажется Вам полезной. В скором времени напишу как можно напечатать эти списки, а за одно и как написать Workflow рассылки под эту задачу в VS.

Автор: ProgramYkt

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js