none
Sharepoint 2013 совместная работа со списками RRS feed

  • Вопрос

  • Добрый день.
    Установлен Sharepoint 2013 Foundation. Обновлен до последней апдейты.
    Для работы пользователей создан общий список. В списке несколько столбцов с которыми должны одновременно работать пользователи.
    Заметил , что когда список открывает один пользователь, вносит изменения и сохраняет их , то второй пользователь одновременно с первым открывший этот же список не может сохранить свои изменения.
    При попытке сохранить свои изменения вторым пользователем выводится сообщение

    "Конфликт сохранения. Внесенные изменения противоречат изменениям, сделанным другим пользователем в это же время. Чтобы применить свои изменения, нажмите в веб-браузере кнопку "Назад", обновите страницу и отправьте изменения повторно"

    подскажите как можно обойти данный конфликт?
    Может быть есть возможность проверять открыт ли список первым пользователем до его открытия вторым и при попытке
    открытия вторым выводить предупреждение?

    Заранее спасибо за любые идеи!

Все ответы

  • Здравствуйте!

    Посмотрите нижеуказанные обсуждения:

    Save Conflict: Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click back in your Web browser, refresh the page, and resubmit your changes


    SharePoint 2013 - Save Conflict


    Save Conflict When editing or uploading attachments to List Item

    Мнения, высказанные здесь, являются отражением моих личных взглядов, а не позиции корпорации Microsoft. Вся информация предоставляется "как есть" без каких-либо гарантий.

    Модератор
  • Добрый день.

    боюсь, что при работе со стандартными формами эту проблему решить не получиться.

    на сервере храниться версия счетчика.

    и не важно в каком порядке кто открыл, важно, чтобы номер счетчика открытой формы был не меньше чем на сервере.

    т.е. если первый пользователь открыл и работает с формой 5 мин. при этом у него счетчик имеет значение допустим 10.

    заходит второй пользователь, открывает этот же элемент, счетчик имеет значение 10, он меняет одно поле и тут же сохраняет.

    первый пользователь нажимает сохранить и у него конфликт сохранения, т.к. у него форма 10, а на сервере уже 11.

    как обойти это я не знаю. если использовать свою форму и сохранять через REST, то там можно в в хедере указать 

    "IF-MATCH": "*",


    мой блог не много о SharePoint

    Модератор
  • Владимир, спасибо.

    Ваш блог читаю давно, очень полезные вещи нашел там. Отдельное спасибо за блог.

    Разбираясь с проблемой я уже понял, что скорее это by design  и в лоб решить нельзя.

    Сейчас думаю как обойти проблему.

    С Sharepoint я начал работать недавно и больше занимаюсь системным администрированием , чем разработкой.

    Хочу сделать следующее

    - в редактор сценариев (через добавление ВЭБ части) вставить JAVA скрипт, который при открытии списка юзером 1 создавал бы файл с именем равным номеру элемента. 

    - соответственно при открытии этого списка юзером 2 с помощью JAVA скрипта идет проверка наличия этого файла, если файл существует , то выводится сообщение , что список занят и возврат на предыдущую страницу

    - при закрытии списка (при нажатии на СОХРАНИТЬ) запускается рабочий процесс, который удаляет файл

    В результате мы избежим одновременного редактирования списка несколькими юзерами.

    По вашему опыту , такой вариант возможен?

    Может быть есть ещё идеи, более грамотные?

  • чем плоха реализация:
    1. пользователь может нажать Отмена, и у вас будет элемент который никто не сможет редактировать. и понять, что его действительно кто-то редактирует или это описанная ситуация будет не просто.
    2. если включено быстрое редактирование, то ваше решение опять же не спасет.
    3. как быть если пользователи одновременно открыли элемент
    4. РП отрабатывает с задержкой и это нужно учитывать. 

    если использовать стандартные формы, то пока предложить вам ничего подходящего не могу. 
     Вот не помню, можно получить версию счетчика через REST. кажется можно. 
    единственный вариант, при открытии формы запоминать время открытия и при сохранении делать синхронный запрос к шарику, посмотреть когда последний раз сохраняли это элемент. Далее нужно найти способ как заставить форму шарика использовать версию счетчика с сервера.

    вы, надеюсь понимаете, что данные могут затираться если вы реализуете требуемое. 
    т.е. ситуация
    два пользователя редактируют элемент одновременно.
    первый поменял 5 полей и сохранил
    второму форма тоже дала сохранить и при этом изменения первого пользователя просто потеряются (найдете только в истории версий)

    мой блог не много о SharePoint

    Модератор
  • Спасибо.

    Несколько вопросов, если позволите

    1. Можно ли как-то обрабатывать событие по нажатию кнопки ОТМЕНА (т.е. идея при нажатии на эту кнопку опять же запускать ЯВА скрипт для удаления файла\флага)

    2. Если использовать свою форму редактирования. Я её создал через Sharepoint Designer , назначил используемой по умолчанию. Немного подробнее можете написать как применить условие о котором вы писали выше ?"IF-MATCH": "*",

    Заранее спасибо!

  • Спасибо.

    Несколько вопросов, если позволите

    1. Можно ли как-то обрабатывать событие по нажатию кнопки ОТМЕНА (т.е. идея при нажатии на эту кнопку опять же запускать ЯВА скрипт для удаления файла\флага)

    можно переопределить действия стандартной кнопки и вызвать свой код, когда он отработает, то можно вызвать стандартное действие

    Wait async query in PreSaveAction

    2. Если использовать свою форму редактирования. Я её создал через Sharepoint Designer , назначил используемой по умолчанию. Немного подробнее можете написать как применить условие о котором вы писали выше ?"IF-MATCH": "*",

    Заранее спасибо!

    я имел ввиду полностью свою форму которая получает и отдает данные через REST

    Avoid concurrency using Etag in SharePoint REST-API Call


    мой блог не много о SharePoint

    Модератор
  • Буду разбираться, спасибо.

    Вот здесь не могу с вами согласиться "вы, надеюсь понимаете, что данные могут затираться если вы реализуете требуемое. 
    т.е. ситуация
    два пользователя редактируют элемент одновременно.
    первый поменял 5 полей и сохранил
    второму форма тоже дала сохранить и при этом изменения первого пользователя просто потеряются (найдете только в истории версий)"

    если мы проверяем наличие файла\флага ДО начала редактирования запроса, то такая ситуация не возникнет. Редактирование разрешено только юзеру 1 , далее выставляется флаг , который блокирует открытие списка 2-м и т.д. юзером.

    В сообщение и блокировке списка , хочу добавить имя пользователя , который открыл список первым, имя планирую поместить в сам файл, не поделитесь идеей как получить имя пользователя открывшего список?

  • _spPageContextInfo.userId;

    мой блог не много о SharePoint

    Модератор
  • есть ещё вариант решения задачи без выставления флагов

    Допустим первый пользователь открыл список и редактирует его, в это время этот же список открывает второй и тоже редактирует. Первый сохраняет, второй делает попытку сохранить и получает вышеописанную ошибку. Можно на форме списка (или в Рибоне) поставить кнопку , назвать РАЗБЛОКИРОВКА, по нажатию кнопки, ЯВА скрипт заносит все значения колонок списка в переменные, обновляет страницу (при этом обновляется версия списка) и возвращает обратно все значения из переменных в поля списка, пользователю 2 надо только повторно нажать СОХРАНИТЬ. В теории должно работать.

  • обновляет страницу (при этом обновляется версия списка) 

    а где останутся данные, если страница перезагрузилась?

    можно посмотреть в сторону локального хранилища браузера


    мой блог не много о SharePoint


    Модератор
  • Записать файл\флаг планировал в SiteAssets, но как оказалось запись\чтение файлов через JQUERY нетривиальная задача.

    Вопрос - можно ли как то для подобной операции прикрутить Powershell скрипт? что бы он вызывался из ВЭБ части через JQUERY и делал необходимые операции с файлами?

    Заранее спасибо!

  • Если вам нужно производить действия с файлами, то там проще. 

    Пользователь может извлекать файлы перед редактированием и тогда никто другой не сможет менять свойства.

    что бы PowerShell работал с шариком это нужно:
    1. выполнять код непосредственно на сервере SharePOint/

    2. через CSOM, но ему нужны файлы (dll). и это еще тот удовольствие работать через CSOM в PowerShell.

    идея не жизнеспособная.


    мой блог не много о SharePoint

    Модератор
  • Мне нужно создать файл (имя файла хотелось бы задать равным ID элемента) в SiteAsset , занести в него имя пользователя открывшего список.

    На втором этапе нужно прочитать этот файл и извлечь его содержимое.

    Разбираясь с этим я понял , что стандартных инструментов для работы с файлами в Jquery нет.

    Делается либо через ActiveX, php, HTML.

    Думал сделать с помощью Powershell , но как оказалось идея нерабочая...

    Может можно использовать в качестве флага не файл , а какое-нибудь поле списка или переменную?


    • Изменено Strannik10 19 мая 2020 г. 12:09

  • Может можно использовать в качестве флага не файл , а какое-нибудь поле списка или переменную?


    вам ни кто не мешает создавать элемент в соседнем списке и в качестве Title указать id открытого элемента.
    зачем вам читать содержимое файла, что вы туда хотите писать?

    мой блог не много о SharePoint

    Модератор
  • Для хранения флага, по которому второй юзер будет определять , что элемент списка уже редактируется первым юзером думаю использовать дополнительное текстовое поле.

    Поле создал в самой форме элемента.

    При открытии элемента первым пользователем в поле заносится значение Block,

    но при открытии этого же элемента вторым поле открывается пустым (значения Block в нем нет)

    судя по всему это происходит потому , что изменения в элементе не сохранены и второй пользователь открывает версию элемента , где поле ещё пустое.

    Вопрос можно ли как то сохранить элемент после изменения значения определенного поля?

    Пробовал программно нажать кнопку СОХРАНИТЬ, она нажимается , но кроме сохранения значения элемента, пользователя выкидывает на предыдущую страницу, а это не подходит.

    Заранее спасибо!

  • скажите, а вы рассматривали сценарии когда пользователь отрыл элемент и в место того, что бы нажать одну из кнопок (сохранить или отмена) сделает одно из следующих действий:
    1. закроет вкладку
    2. закроет браузер

    3. перейдет в другой раздел по средствам навигации

    4. в этой же вкладке вставит другой URL и перейдет


    мой блог не много о SharePoint

    Модератор
  • задача становится ещё более интересной...
  • При решении задачи возник вопрос:

    как запустить рабочий процесс списка из Jquery помещенного в редактор контента?

    Заранее спасибо за ответ.

  • Всем спасибо, кто помог, натолкнул на нужные мысли.

    В первом приближении проблема решена.

    Программных блокировок с помощью флага не делал.

    Решил так

    1. Пользователь 1 открывает элемент списка и начинает его редактировать, в это время Пользователь 2 открывает этот же элемент и тоже начинает редактировать.

    2. Пользователь 1 нажимает СОХРАНИТЬ, в это время обработчик (код ниже) перехватывает нажатие кнопки и заносит все значения столбцов в переменные, далее вызывается функция UPDATE с помощью этого пакета https://aymkdn.github.io/SharepointPlus/lists.html#update , после того как UPDATE выполнен версия элемента меняется, а пользователь 1 перенаправляется на предыдущую страницу.

    3. Теперь Пользователь 2 нажимает СОХРАНИТЬ , происходит такой же перехват нажатия кнопки, далее UPDATE элемента, автоматически меняется версия и пользователь перенаправляется на пред. страницу.

    В итоге сохраняются данные и от Пользователя 1 и от П2.

    Вот код на Jquery. Это вообще мой первый код на Ява, не пинайте сильно.

    <script src="/bz/SiteAssets/jquery-3.5.0.min.js" type="text/javascript"></script><script src="/bz/SiteAssets/sharepointplus.js" type="text/javascript"></script><script src="/bz/SiteAssets/sputility.min.js" type="text/javascript"></script><script src="/bz/SiteAssets/jquery.SPServices.min.js" type="text/javascript"></script><script> 
       
    $(document).ready(function()

    {

    //Set the Field to Read only and change its background colour

    $("input[title='Номер запроса']").attr("readonly","true").css('background-color','#FFF8DC');

    $("Textarea[title='Диалог']").attr("readonly","true").css('background-color','#FDF5E6');

    //You can disable the field also:  $("input[Title='ID']").attr("disabled", "disabled");

    });   
       

    var originalSaveButtonClickHandler = function(){};

    $(document).ready( function() {
      var saveButton = $("[name$='diidIOSaveItem']")   //gets form save button and ribbon save button
      if (saveButton.length > 0) {
        originalSaveButtonClickHandler = saveButton[0].onclick;   //save original function
      }
      $(saveButton).attr("onclick", "ValidateFormSave()");   //change onclick to execute our custom validation function
    });

    function ValidateFormSave() { 
    //execute your async functions here
      var clientContext = SP.ClientContext.get_current();
      var templates = clientContext.get_site().get_rootWeb().getAvailableWebTemplates(1033, false);
      clientContext.load(templates);
      clientContext.executeQueryAsync(
        function() {
     
     //     alert ('Success! Save!');
            MySave();
      //    originalCancelButtonClickHandler();
       //   window.location = window.location;
      //    originalSaveButtonClickHandler();   //make sure to call this on your final success callback
        }, 
        function() {alert ('Failure.Save.')}
      );
    }

    var originalCancelButtonClickHandler = function(){};

    $(document).ready( function () {
      var cancelButton = $("[name$='diidIOGoBack']")   //gets form cancel button and ribbon save button
      if (cancelButton.length > 0) {
        originalCancelButtonClickHandler = cancelButton[0].onclick;   //cancel original function
      }
      $(cancelButton).attr("onclick", "ValidateFormCancel()");   //change onclick to execute our custom validation function
    });

    function ValidateFormCancel() { 
    //execute your async functions here
      var clientContext = SP.ClientContext.get_current();
      var templates = clientContext.get_site().get_rootWeb().getAvailableWebTemplates(1033, false);
      clientContext.load(templates);
      clientContext.executeQueryAsync(
        function() {
    //      alert ('Success! Cancel!');
          originalCancelButtonClickHandler();   //make sure to call this on your final success callback
        }, 
        function() {alert ('Failure.Cancel.')}
      );
    }

       
     function MySave() { 

    //alert('start');

    var Myid =$("input[title='Номер запроса']").val();

    var MyTextZaprosa =$("Textarea[title='Текст запроса']").text();

    var MyTema =$("select[title='Тема'] option:selected").text();

    var MyStatus =$("select[title='Состояние'] option:selected").text();

    var MyUrgency =$("select[title='Срочность'] option:selected").text();

    var MyKomuSoobshit =$('div#ctl00_ctl26_g_265b926b_907d_40d9_8a85_2ff5beb6b9c7_ctl00_ctl05_ctl03_ctl00_ctl00_ctl05_ctl00_ctl00_UserField_upLevelDiv').text();

    var MyKomuSoobshit ='-1;#'+MyKomuSoobshit;

    $SP().list("Служба запросов").update([{ID:Myid, Discussion:MyTextZaprosa}, {ID:Myid, Subject:MyTema}, {ID:Myid, Status:MyStatus}, {ID:Myid, Urgency:MyUrgency}, {ID:Myid, Responsible:MyKomuSoobshit}]);
           
     $SP().notify('Сохраняем...', {
        name:"My 2 seconds notification",
        timeout:2,
        after:function(name,afterDelay) {
          if (afterDelay) {
          window.location.replace("https://start.arlafoods.ru/bz/Lists/Request_Service");
          }
          else alert("Something just removed this notification called '"+name+"'' before the timeout :-(")
        }
      })


    }

    </script> 

  • есть пару ссылок, которые могу помочь
    тут описано как можно получить свойства в поле PeoplePier

    Проверка выбранного значение в PeoplePicker при сохранении элемента

    тут какие свойства можно получить прямо из поля (без доп запросов)Заполнение свойств сотрудника при выборе его в People picker.


    мой блог не много о SharePoint

    Модератор
  • Владимир, сейчас активно пользуюсь методикой описанной в вашем блоге

    https://kaplin-vladimir.blogspot.com/2014/12/jquery-jquery-sharepoint-2013-fields.html

    код такой

    _spBodyOnLoadFunctionNames.push("changeTema");
     
    function changeTema()
    {
    $("Select[title='Тема']").change(function () {
    //setTitle();
    if ($("select[title='Тема'] option:selected").text() == 'IT_Вопросы по ИТ') {$('div#ctl00_ctl26_g_8b43cf0d_d196_4c2f_8b07_0df4f28b2043_ctl00_ctl05_ctl03_ctl00_ctl00_ctl05_ctl00_ctl00_UserField_upLevelDiv').text('test')};
    });

    }

    всё работает, но у меня в выпадающем списке более 20 строк. Я читал , что

    Sharepoint по разному рендерит элемент combobox взависимости от кол-ва строк.

    Пытаюсь адаптировать к кол-ву более 20. Вот мой код

    function changeTema()
    {
    $("input[title='Тема']").change(function () {
    //setTitle();
    if ($("input[title='Тема'] option:selected").text() == 'IT_Вопросы по ИТ') {$('div#ctl00_ctl26_g_8b43cf0d_d196_4c2f_8b07_0df4f28b2043_ctl00_ctl05_ctl03_ctl00_ctl00_ctl05_ctl00_ctl00_UserField_upLevelDiv').text('test')};
    });

    }

    но он не работает, может быть подскажите где ошибка?

    Заранее спасибо!